带有 JSF 的 Servlet 过滤器
Posted
技术标签:
【中文标题】带有 JSF 的 Servlet 过滤器【英文标题】:Servlet filter with JSF 【发布时间】:2015-01-02 23:03:22 【问题描述】:我尝试使用 JSF 配置 Servlet 过滤器。我在这里遇到很多问题,我也在使用 PrimeFaces。
这是我的 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>JsfEaxmples</display-name>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
<param-value>1</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.SEPARATOR_CHAR</param-name>
<param-value>-</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.skin</param-name>
<param-value>classic</param-value>
</context-param>
<context-param>
<param-name>facelets.BUILD_BEFORE_RESTORE</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>facelets.RECREATE_VALUE_EXPRESSION_ON_BUILD_BEFORE_RESTORE</param-name>
<param-value>true</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<filter>
<filter-name>sessionfilter</filter-name>
<filter-class>com.invoice.sessionfilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sessionfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
首先我使用这样的过滤器<url-pattern>jsf invoice system/*</url-pattern>
this 完全不起作用所以我改为<url-pattern>/*</url-pattern>
this 响应但在我的过滤中出现了很多问题
我用过滤器检查以下这些过程
-
如果会话不存在,用户应该被重定向到登录页面
如果会话存在并且如果用户进入登录页面,他不应该被重定向
在添加过滤器 PrimeFaces 组件外观更改后进行更多操作。添加过滤器后,无法正确导航。
这是我的过滤器代码。
package com.invoice;
import java.io.IOException;
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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class sessionfilter implements Filter
String uname;
/**
* Default constructor.
*/
public sessionfilter()
// TODO Auto-generated constructor stub
/**
* @see Filter#destroy()
*/
public void destroy()
// TODO Auto-generated method stub
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
// place your code here
// pass the request along the filter chain
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String pagerequested = req.getRequestURL().toString();
HttpSession ses = req.getSession(true);
//uname=(String)ses.getAttribute("uname");//null pointer exception
if (pagerequested.contains("Login.xhtml") && uname == null)// if user logs in to this for first time
chain.doFilter(request, response);
else if (uname != null && pagerequested.contains("Login.xhtml")) // if session exists and user tries to go to login page he should be redirected
resp.sendRedirect("invoiceinfo.xhtml");
else if (uname == null && !pagerequested.contains("Login.xhtml"))
try
uname = (String) ses.getAttribute("uname");
chain.doFilter(request, response);
catch (Exception e)
resp.sendRedirect("Login.xhtml");
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException
// TODO Auto-generated method stub
这是我的登录 bean,会话范围为我在这里不使用注释
package com.invoice;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;
@SessionScoped
public class login
String username, userpassword, errormess, navipg;
public String getNavipg()
return navipg;
public void setNavipg(String navipg)
this.navipg = navipg;
public String getErrormess()
return errormess;
public void setErrormess(String errormess)
this.errormess = errormess;
public String getUsername()
return username;
public void setUsername(String username)
this.username = username;
public String getUserpassword()
return userpassword;
public void setUserpassword(String userpassword)
this.userpassword = userpassword;
public String navigate()
try
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "invoice", "google");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select username,password from usertable where username='" + username + "' and password='" + userpassword + "' ");
if (rs.next())
setErrormess("");
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("uname", this.username);
navipg = "invoiceinfo";
else
setErrormess("Invalid Login credentials");
username = "";
navipg = "Login";
catch (Exception e)
e.printStackTrace();
return navipg;
public String logout()
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "Login";
我的登录页面是
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<style type="text/css">
.ui-panelgrid tr,
.ui-panelgrid td
border: none;
</style>
</h:head>
<h:body>
<h:form>
<p:panelGrid columns="3" id="pnl" border= "0">
<f:facet name="header"><p:graphicImage value="login.jpg"/></f:facet>
<h:outputText value="Username"/>
<p:inputText id="uname" value="#login.username" required="true" label="username"/>
<p:message for="uname"/>
<h:outputText value="Password"/>
<p:password id="pass" value="#login.userpassword" required="true" label="password"/>
<p:message for="pass"/>
<p:commandButton value="Login" action="#login.navigate" ajax="false"/>
<p:button value="Reset" />
</p:panelGrid>
<h1><h:outputText value="#login.errormess"/></h1>
</h:form>
</h:body>
</html>
我完全被困在这里,不知道如何进行过滤。
【问题讨论】:
参考这个***.com/questions/8480100/… “不起作用”是什么意思?例外?错误? “不起作用”描述了什么行为? 我没有得到想要的输出,我的意思是页面是空白的 【参考方案1】:对于 CDI,我使用它。似乎工作正常。也重定向 ajax 请求。
所有页面都在 /secure/ 中,除了 login.xhtml 在根目录中。
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>...LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/secure/*</url-pattern>
</filter-mapping>
过滤器:
@Inject
private LoginBean loginBean;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
// Set response headers to no-cache
HttpServletResponse res = (HttpServletResponse) response;
HttpServletRequest req = (HttpServletRequest) request;
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
res.setDateHeader("Expires", 0); // Proxies.
// Check if user logged in, if not redirect to login.xhtml
if (loginBean == null || !((LoginBean) loginBean).isLoggedIn())
boolean isAjax = "XMLHttpRequest".equals(req.getHeader("X-Requested-With"));
if (!isAjax)
res.sendRedirect(req.getContextPath() + "/login.xhtml");
else
// Redirecting an ajax request has to be done in the following way:
// http://javaevangelist.blogspot.dk/2013/01/jsf-2x-tip-of-day-ajax-redirection-from.html
String redirectURL = res.encodeRedirectURL(req.getContextPath() + "/login.xhtml");
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><partial-response><redirect url=\"").append(redirectURL).append("\"></redirect></partial-response>");
res.setCharacterEncoding("UTF-8");
res.setContentType("text/xml");
PrintWriter pw = response.getWriter();
pw.println(sb.toString());
pw.flush();
else
// Let chain of filters continue;
chain.doFilter(request, response);
login.xhtml:
<h:body onload="PF('dlg').show()">
<p:growl id="growl" life="5000" autoUpdate="true" showDetail="true" escape="false"/>
<h:form>
<p:dialog id="dialog" header="Login" footer="..." widgetVar="dlg" closable="false" showEffect="clip" draggable="false" resizable="false" style="box-shadow: 7px 10px 5px #303030;">
<p:panelGrid columns="2">
<p:outputLabel value="Username"/>
<p:inputText value="#loginBean.username" id="username"/>
<p:outputLabel value="Password"/>
<p:password value="#loginBean.password" id="password"/>
</p:panelGrid>
<p:commandButton id="button" value="Login" action="#loginBean.doLogin" style="float:right"/>
.... close tags
LoginBean 是一个简单的 SessionScoped CDI bean。
【讨论】:
什么是 /secure/* 我不明白 一个文件夹和一个 url 模式 没错。对该文件夹中的任何内容的请求都会触发过滤器 好的,我的情况是这样 jsfeaxmples 是项目名称,在项目内部我有一个名为 Jsf Invoice System 的文件夹,所以我更改了这样的 url以上是关于带有 JSF 的 Servlet 过滤器的主要内容,如果未能解决你的问题,请参考以下文章
从 servlet 过滤器重定向到 jsf 会返回未呈现为 html 的实际 jsf 代码
Java Servlet 过滤器和其他对象和实体管理器的范围
JSF -- 过滤 javax.faces.resource 文本替换
如何在 Tomcat 上运行的 servlet 过滤器中使用 HttpServletRequest#getParts()?