Polish
This commit is contained in:
45
samples/javaconfig/users/src/main/java/sample/Account.java
Normal file
45
samples/javaconfig/users/src/main/java/sample/Account.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample;
|
||||
|
||||
public class Account {
|
||||
private String username;
|
||||
|
||||
private String logoutUrl;
|
||||
|
||||
private String switchAccountUrl;
|
||||
|
||||
public Account(String username, String logoutUrl, String switchAccountUrl) {
|
||||
super();
|
||||
this.username = username;
|
||||
this.logoutUrl = logoutUrl;
|
||||
this.switchAccountUrl = switchAccountUrl;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
public String getLogoutUrl() {
|
||||
return this.logoutUrl;
|
||||
}
|
||||
|
||||
public String getSwitchAccountUrl() {
|
||||
return this.switchAccountUrl;
|
||||
}
|
||||
|
||||
}
|
||||
38
samples/javaconfig/users/src/main/java/sample/Config.java
Normal file
38
samples/javaconfig/users/src/main/java/sample/Config.java
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*/
|
||||
|
||||
// tag::class[]
|
||||
@Configuration
|
||||
@EnableRedisHttpSession
|
||||
public class Config {
|
||||
|
||||
@Bean
|
||||
public LettuceConnectionFactory connectionFactory() {
|
||||
return new LettuceConnectionFactory();
|
||||
}
|
||||
}
|
||||
// end::class[]
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public class Initializer extends AbstractHttpSessionApplicationInitializer {
|
||||
|
||||
public Initializer() {
|
||||
super(Config.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterSessionRepositoryFilter(ServletContext servletContext) {
|
||||
appendFilters(servletContext, new UserAccountsFilter());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet("/login")
|
||||
public class LoginServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
String username = req.getParameter("username");
|
||||
String password = req.getParameter("password");
|
||||
|
||||
if (username != null && !"".equals(username) && username.equals(password)) {
|
||||
req.getSession().setAttribute("username", username);
|
||||
String url = resp.encodeRedirectURL(req.getContextPath() + "/");
|
||||
resp.sendRedirect(url);
|
||||
}
|
||||
else {
|
||||
String url = resp.encodeRedirectURL(req.getContextPath() + "/?error");
|
||||
resp.sendRedirect(url);
|
||||
}
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -8157634860354132501L;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
@WebServlet("/logout")
|
||||
public class LogoutServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
HttpSession session = req.getSession(false);
|
||||
if (session != null) {
|
||||
session.invalidate();
|
||||
}
|
||||
String url = resp.encodeRedirectURL(req.getContextPath() + "/");
|
||||
resp.sendRedirect(url);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 4061762524521437433L;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.session.Session;
|
||||
import org.springframework.session.SessionRepository;
|
||||
import org.springframework.session.web.http.HttpSessionManager;
|
||||
|
||||
public class UserAccountsFilter implements Filter {
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
|
||||
// tag::HttpSessionManager[]
|
||||
HttpSessionManager sessionManager = (HttpSessionManager) httpRequest
|
||||
.getAttribute(HttpSessionManager.class.getName());
|
||||
// end::HttpSessionManager[]
|
||||
SessionRepository<Session> repo = (SessionRepository<Session>) httpRequest
|
||||
.getAttribute(SessionRepository.class.getName());
|
||||
|
||||
String currentSessionAlias = sessionManager.getCurrentSessionAlias(httpRequest);
|
||||
Map<String, String> sessionIds = sessionManager.getSessionIds(httpRequest);
|
||||
String unauthenticatedAlias = null;
|
||||
|
||||
String contextPath = httpRequest.getContextPath();
|
||||
List<Account> accounts = new ArrayList<Account>();
|
||||
Account currentAccount = null;
|
||||
for (Map.Entry<String, String> entry : sessionIds.entrySet()) {
|
||||
String alias = entry.getKey();
|
||||
String sessionId = entry.getValue();
|
||||
|
||||
Session session = repo.getSession(sessionId);
|
||||
if (session == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String username = session.getAttribute("username");
|
||||
if (username == null) {
|
||||
unauthenticatedAlias = alias;
|
||||
continue;
|
||||
}
|
||||
|
||||
String logoutUrl = sessionManager.encodeURL("./logout", alias);
|
||||
String switchAccountUrl = sessionManager.encodeURL("./", alias);
|
||||
Account account = new Account(username, logoutUrl, switchAccountUrl);
|
||||
if (currentSessionAlias.equals(alias)) {
|
||||
currentAccount = account;
|
||||
}
|
||||
else {
|
||||
accounts.add(account);
|
||||
}
|
||||
}
|
||||
|
||||
// tag::addAccountUrl[]
|
||||
String addAlias = unauthenticatedAlias == null ? // <1>
|
||||
sessionManager.getNewSessionAlias(httpRequest)
|
||||
: // <2>
|
||||
unauthenticatedAlias; // <3>
|
||||
String addAccountUrl = sessionManager.encodeURL(contextPath, addAlias); // <4>
|
||||
// end::addAccountUrl[]
|
||||
|
||||
httpRequest.setAttribute("currentAccount", currentAccount);
|
||||
httpRequest.setAttribute("addAccountUrl", addAccountUrl);
|
||||
httpRequest.setAttribute("accounts", accounts);
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*!
|
||||
* IE10 viewport hack for Surface/desktop Windows 8 bug
|
||||
* Copyright 2014 Twitter, Inc.
|
||||
* Licensed under the Creative Commons Attribution 3.0 Unported License. For
|
||||
* details, see http://creativecommons.org/licenses/by/3.0/.
|
||||
*/
|
||||
|
||||
// See the Getting Started docs for more information:
|
||||
// http://getbootstrap.com/getting-started/#support-ie10-width
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
|
||||
var msViewportStyle = document.createElement('style')
|
||||
msViewportStyle.appendChild(
|
||||
document.createTextNode(
|
||||
'@-ms-viewport{width:auto!important}'
|
||||
)
|
||||
)
|
||||
document.querySelector('head').appendChild(msViewportStyle)
|
||||
}
|
||||
})();
|
||||
112
samples/javaconfig/users/src/main/webapp/index.jsp
Normal file
112
samples/javaconfig/users/src/main/webapp/index.jsp
Normal file
@@ -0,0 +1,112 @@
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib prefix="wj" uri="http://www.webjars.org/tags" %>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Demonstrates Multi User Log In</title>
|
||||
<wj:locate path="bootstrap.min.css" relativeTo="META-INF/resources" var="bootstrapCssLocation"/>
|
||||
<link rel="stylesheet" href="<c:url value="${bootstrapCssLocation}"/>">
|
||||
<style type="text/css">
|
||||
body {
|
||||
padding: 1em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<!-- Static navbar -->
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://github.com/spring-projects/spring-session/">Spring Session</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<c:url value="/" var="homeUrl"/>
|
||||
<li class="active"><a id="navHome" href="${homeUrl}">Home</a></li>
|
||||
<li>
|
||||
<!-- tag::link[]
|
||||
-->
|
||||
<c:url value="/link.jsp" var="linkUrl"/>
|
||||
<a id="navLink" href="${linkUrl}">Link</a>
|
||||
<!-- end::link[]
|
||||
-->
|
||||
</li>
|
||||
</ul>
|
||||
<c:if test="${currentAccount != null or not empty accounts}">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a id="toggle" href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><c:out value="${username}"/> <span class="caret"></span></a>
|
||||
<ul id="user-menu" class="dropdown-menu" role="menu">
|
||||
<c:if test="${currentAccount != null}">
|
||||
<li><a id="logout" href="${currentAccount.logoutUrl}">Log Out</a></li>
|
||||
<li><a id="addAccount" href="${addAccountUrl}">Add Account</a></li>
|
||||
</c:if>
|
||||
<c:if test="${not empty accounts}">
|
||||
<li class="divider"></li>
|
||||
<li class="dropdown-header">Switch Account</li>
|
||||
<li class="divider"></li>
|
||||
</c:if>
|
||||
<c:forEach items="${accounts}" var="account">
|
||||
<c:set var="encodedUsername">
|
||||
<c:out value="${account.username}"/>
|
||||
</c:set>
|
||||
<li><a id="switchAccount${encodedUsername}" href="${account.switchAccountUrl}"><c:out value="${account.username}"/></a></li>
|
||||
</c:forEach>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</c:if>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div><!--/.container-fluid -->
|
||||
</nav>
|
||||
|
||||
<h1>Description</h1>
|
||||
<p>This application demonstrates how to use Spring Session to authenticate as multiple users at a time. View authenticated users in the upper right corner.</p>
|
||||
|
||||
<c:choose>
|
||||
<c:when test="${username == null}">
|
||||
<h1>Please Log In</h1>
|
||||
<p>You are not currently authenticated with this session. You can authenticate with any username password combination that are equal. A few examples to try:</p>
|
||||
<ul>
|
||||
<li><b>Username</b> rob and <b>Password</b> rob</li>
|
||||
<li><b>Username</b> luke and <b>Password</b> luke</li>
|
||||
</ul>
|
||||
<c:if test="${param.error != null}">
|
||||
<div id="error" class="alert alert-danger">Invalid username / password. Please ensure the username is the same as the password.</div>
|
||||
</c:if>
|
||||
<c:url value="/login" var="loginUrl"/>
|
||||
<form action="${loginUrl}" method="post">
|
||||
<div class="form-group">
|
||||
<label for="username">Username</label>
|
||||
<input id="username" type="text" name="username"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input id="password" type="password" name="password"/>
|
||||
</div>
|
||||
<input type="submit" value="Login"/>
|
||||
</form>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<h1 id="un"><c:out value="${username}"/></h1>
|
||||
<p>You are authenticated as <b><c:out value="${username}"/></b>. Observe that you can <a href="${linkUrl}">navigate links</a> and the correct session is used. Using the links in the upper right corner you can:</p>
|
||||
<ul>
|
||||
<li>Log Out</li>
|
||||
<li>Switch Accounts</li>
|
||||
<li>Add Account</li>
|
||||
</ul>
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</div>
|
||||
<!-- Bootstrap core JavaScript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<wj:locate path="jquery.min.js" relativeTo="META-INF/resources" var="jqueryLocation"/>
|
||||
<script src="<c:url value="${jqueryLocation}"/>"></script>
|
||||
<wj:locate path="bootstrap.min.js" relativeTo="META-INF/resources" var="bootstrapJsLocation"/>
|
||||
<script src="<c:url value="${bootstrapJsLocation}"/>"></script>
|
||||
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
|
||||
<script src="<c:url value="/assets/js/ie10-viewport-bug-workaround.js"/>"></script>
|
||||
</body>
|
||||
</html>
|
||||
85
samples/javaconfig/users/src/main/webapp/link.jsp
Normal file
85
samples/javaconfig/users/src/main/webapp/link.jsp
Normal file
@@ -0,0 +1,85 @@
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib prefix="wj" uri="http://www.webjars.org/tags" %>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Linked Page</title>
|
||||
<wj:locate path="bootstrap.min.css" relativeTo="META-INF/resources" var="bootstrapCssLocation"/>
|
||||
<link rel="stylesheet" href="<c:url value="${bootstrapCssLocation}"/>">
|
||||
<style type="text/css">
|
||||
body {
|
||||
padding: 1em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<!-- Static navbar -->
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="https://github.com/spring-projects/spring-session/">Spring Session</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<c:url value="/" var="homeUrl"/>
|
||||
<li><a id="navHome" href="${homeUrl}">Home</a></li>
|
||||
<c:url value="/link.jsp" var="linkUrl"/>
|
||||
<li class="active"><a id="navLink" href="${linkUrl}">Link</a></li>
|
||||
|
||||
</ul>
|
||||
<c:if test="${currentAccount != null or not empty accounts}">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a id="toggle" href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><c:out value="${username}"/> <span class="caret"></span></a>
|
||||
<ul id="user-menu" class="dropdown-menu" role="menu">
|
||||
<c:if test="${currentAccount != null}">
|
||||
<li><a id="logout" href="${currentAccount.logoutUrl}">Log Out</a></li>
|
||||
<li><a id="addAccount" href="${addAccountUrl}">Add Account</a></li>
|
||||
</c:if>
|
||||
<c:if test="${not empty accounts}">
|
||||
<li class="divider"></li>
|
||||
<li class="dropdown-header">Switch Account</li>
|
||||
<li class="divider"></li>
|
||||
</c:if>
|
||||
<c:forEach items="${accounts}" var="account">
|
||||
<li><a id="switchAccount${account.username}" href="${account.switchAccountUrl}"><c:out value="${account.username}"/></a></li>
|
||||
</c:forEach>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</c:if>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div><!--/.container-fluid -->
|
||||
</nav>
|
||||
|
||||
<h1>Description</h1>
|
||||
<p>This page demonstrates how we keep track of the correct user session between links even when multiple tabs are open. Try opening another tab with a different user and browse. Then come back to the original tab and see the correct user is maintained.</p>
|
||||
|
||||
<c:choose>
|
||||
<c:when test="${username == null}">
|
||||
<h1>Please Log In</h1>
|
||||
<p>You are not currently authenticated with this session. <a href="${homeUrl}">Log In</a></p>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<h1 id="un"><c:out value="${username}"/></h1>
|
||||
<p>You are authenticated as <b><c:out value="${username}"/></b>. Observe that you can <a href="${linkUrl}">navigate links</a> and the correct session is used. Using the links in the upper right corner you can:</p>
|
||||
<ul>
|
||||
<li>Log Out</li>
|
||||
<li>Switch Accounts</li>
|
||||
<li>Add Account</li>
|
||||
</ul>
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</div>
|
||||
<!-- Bootstrap core JavaScript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<wj:locate path="jquery.min.js" relativeTo="META-INF/resources" var="jqueryLocation"/>
|
||||
<script src="<c:url value="${jqueryLocation}"/>"></script>
|
||||
<wj:locate path="bootstrap.min.js" relativeTo="META-INF/resources" var="bootstrapJsLocation"/>
|
||||
<script src="<c:url value="${bootstrapJsLocation}"/>"></script>
|
||||
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
|
||||
<script src="<c:url value="/assets/js/ie10-viewport-bug-workaround.js"/>"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user