`
arkxu
  • 浏览: 43282 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

CAS, Liferay和Alfresco portlet三者的整合

阅读更多
CAS 和Liferay的整合网上到处都有,我在此也不再鳌述。CAS和Alfresco的整合推荐一篇blog,你看了之后也就知道怎么做了:
http://athenalogics.blogspot.com/2008/07/how-to-casify-alfresco-cms_567.html

本文所要讲的是在CAS和Liferay已经整合好的前提下, 把Alfresco部署成Liferay的portlet并且和CAS整合。
我试了网上有一些别的方法无一成功,也有人说存在bug无法整合。至少根据我前面的blog讲share liferay session的方法给alfresco portlet是不可行的。alfresco的用户认证这里确实有bug。

当然,首先你需要把Alfresco部署成portlet,我这里用到的是Alfresco community version 2.1, Liferay 5.1.0
部署Liferay portlet 通常的做法是 Hotdeploy. 也就是把alfresco.war放到$user_home/liferay/deploy

之后会在Webapp下面产生一个新的alfresco的app, 到它的lib下面把portlet-api删掉,因为这个和liferay的相冲突。然再把附件中的liferay portlet描述文件copy到alfresco/WEB-INF下面. 注意,附件里的web.xml中用到的portlet-class是我自己修改过的。
这样你的alfresco就可以被添加到liferay里面了.

当然,如果你不想使用hotdeploy(通常写自动产生server的script的人最讨厌这个), 那么可以参考这个script的相应部分: http://tempo.intalio.org/tempo/trunk/rsc/scripts/create_tomcat.rb


接下来,Alfresco portlet的用户管理的基本思路是在PortletSession里是否存在'AuthenticationHelper.AUTHENTICATION_USER'这个属性,如果存在的话就取出里面的User去做验证。通过的话就可以访问。基于这个原理,我在原有的portlet-class上做了一些改动,下面的portlet class的全文:

/*
 * Copyright (C) 2005-2007 Alfresco Software Limited.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

 * As a special exception to the terms and conditions of version 2.0 of 
 * the GPL, you may redistribute this Program in connection with Free/Libre 
 * and Open Source Software ("FLOSS") applications as described in Alfresco's 
 * FLOSS exception.  You should have recieved a copy of the text describing 
 * the FLOSS exception, and it is also available here: 
 * http://www.alfresco.com/legal/licensing"
 */
package org.intalio.tempo.web;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;

import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletRequest;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.UnavailableException;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.UserTransaction;

import org.alfresco.config.ConfigService;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.TempFileProvider;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.portlet.AlfrescoDefaultViewSelector;
import org.alfresco.web.app.servlet.AuthenticationHelper;
import org.alfresco.web.app.servlet.AuthenticationStatus;
import org.alfresco.web.bean.ErrorBean;
import org.alfresco.web.bean.FileUploadBean;
import org.alfresco.web.bean.LoginBean;
import org.alfresco.web.bean.NavigationBean;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.repository.User;
import org.alfresco.web.config.ClientConfigElement;
import org.alfresco.web.config.LanguagesConfigElement;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.portlet.PortletFileUpload;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.portlet.MyFacesGenericPortlet;
import org.apache.myfaces.portlet.PortletUtil;
import org.springframework.web.context.WebApplicationContext;

import com.liferay.portal.service.UserServiceUtil;

/**
 * Class to extend the MyFacesGenericPortlet to provide behaviour specific to
 * Alfresco web client. Handles upload of multi-part forms through a JSR-168
 * Portlet, generic error handling and session login authentication.
 * 
 * @author Gavin Cornwell, Kevin Roast
 */
public class AlfrescoFacesPortlet extends MyFacesGenericPortlet {
    private static final String PREF_ALF_USERNAME = "_alfUserName";
    private static final String SESSION_LAST_VIEW_ID = "_alfLastViewId";

    private static final String ERROR_PAGE_PARAM = "error-page";
    private static final String ERROR_OCCURRED = "error-occurred";
    private List<String> m_languages;
    private static Log logger = LogFactory.getLog(AlfrescoFacesPortlet.class);

    private String loginPage = null;
    private String errorPage = null;

    /**
     * Called by the portlet container to allow the portlet to process an action
     * request.
     */
    public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException {
        Application.setInPortalServer(true);

        // Set the current locale
        I18NUtil.setLocale(Application.getLanguage(request.getPortletSession()));

        boolean isMultipart = PortletFileUpload.isMultipartContent(request);

        try {
            // NOTE: Due to filters not being called within portlets we can not
            // make use
            // of the MyFaces file upload support, therefore we are using a pure
            // portlet request/action to handle file uploads until there is a
            // solution.

            if (isMultipart) {
                if (logger.isDebugEnabled())
                    logger.debug("Handling multipart request...");

                PortletSession session = request.getPortletSession();

                // get the file from the request and put it in the session
                DiskFileItemFactory factory = new DiskFileItemFactory();
                PortletFileUpload upload = new PortletFileUpload(factory);
                List<FileItem> fileItems = upload.parseRequest(request);
                Iterator<FileItem> iter = fileItems.iterator();
                FileUploadBean bean = new FileUploadBean();
                while (iter.hasNext()) {
                    FileItem item = iter.next();
                    String filename = item.getName();
                    if (item.isFormField() == false) {
                        if (logger.isDebugEnabled())
                            logger.debug("Processing uploaded file: " + filename);

                        // workaround a bug in IE where the full path is
                        // returned
                        // IE is only available for Windows so only check for
                        // the Windows path separator
                        int idx = filename.lastIndexOf('\\');

                        if (idx == -1) {
                            // if there is no windows path separator check for
                            // *nix
                            idx = filename.lastIndexOf('/');
                        }

                        if (idx != -1) {
                            filename = filename.substring(idx + File.separator.length());
                        }

                        File tempFile = TempFileProvider.createTempFile("alfresco", ".upload");
                        item.write(tempFile);
                        bean.setFile(tempFile);
                        bean.setFileName(filename);
                        bean.setFilePath(tempFile.getAbsolutePath());
                        session.setAttribute(FileUploadBean.FILE_UPLOAD_BEAN_NAME, bean, PortletSession.PORTLET_SCOPE);
                    }
                }

                // Set the VIEW_ID parameter to tell the faces portlet bridge to
                // treat the request
                // as a JSF request, this will send us back to the previous page
                // we came from.
                String lastViewId = (String) request.getPortletSession().getAttribute(SESSION_LAST_VIEW_ID);
                if (lastViewId != null) {
                    response.setRenderParameter(VIEW_ID, lastViewId);
                }
            } else {
                User user = (User) request.getPortletSession().getAttribute(AuthenticationHelper.AUTHENTICATION_USER);
                if (user != null) {
                    // setup the authentication context
                    try {
                        WebApplicationContext ctx = (WebApplicationContext) getPortletContext().getAttribute(
                                        WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
                        AuthenticationService auth = (AuthenticationService) ctx.getBean("AuthenticationService");
                        auth.validate(user.getTicket());

                        // save last username into portlet preferences, get from
                        // LoginBean state
                        LoginBean loginBean = (LoginBean) request.getPortletSession().getAttribute(AuthenticationHelper.LOGIN_BEAN);
                        if (loginBean != null) {
                            // TODO: Need to login to the Portal to get a user
                            // here to store prefs against
                            // so not really a suitable solution as they get
                            // thrown away at present!
                            // Also would need to store prefs PER user - so auto
                            // login for each...?
                            String oldValue = request.getPreferences().getValue(PREF_ALF_USERNAME, null);
                            if (oldValue == null || oldValue.equals(loginBean.getUsernameInternal()) == false) {
                                if (request.getPreferences().isReadOnly(PREF_ALF_USERNAME) == false) {
                                    request.getPreferences().setValue(PREF_ALF_USERNAME, loginBean.getUsernameInternal());
                                    request.getPreferences().store();
                                }
                            }
                        }

                        // do the normal JSF processing
                        super.processAction(request, response);
                    } catch (AuthenticationException authErr) {
                        // remove User object as it's now useless
                        request.getPortletSession().removeAttribute(AuthenticationHelper.AUTHENTICATION_USER);
                    }
                } else {
                    // do the normal JSF processing as we may be on the login
                    // page
                    super.processAction(request, response);
                }
            }
        } catch (Throwable e) {
            if (getErrorPage() != null) {
                handleError(request, response, e);
            } else {
                logger.warn("No error page configured, re-throwing exception");

                if (e instanceof PortletException) {
                    throw (PortletException) e;
                } else if (e instanceof IOException) {
                    throw (IOException) e;
                } else {
                    throw new PortletException(e);
                }
            }
        }
    }

    /**
     * @see org.apache.myfaces.portlet.MyFacesGenericPortlet#facesRender(javax.portlet.RenderRequest,
     *      javax.portlet.RenderResponse)
     */
    protected void facesRender(RenderRequest request, RenderResponse response) throws PortletException, IOException {

        try {
            User user = (User) request.getPortletSession().getAttribute(AuthenticationHelper.AUTHENTICATION_USER);
            if (user == null) {
                Method getHttpServletRequest = request.getClass().getMethod("getHttpServletRequest");
                HttpServletRequest hsr = (HttpServletRequest) getHttpServletRequest.invoke(request);
                Long userID = (Long) hsr.getSession().getAttribute("USER_ID");
                com.liferay.portal.model.User liferayUser = UserServiceUtil.getUserById(userID);
                String userName = liferayUser.getScreenName();
                logger.debug("user name for alfresco is:" + userName);
                getPortletContext().removeAttribute("loggedin");
                setAuthenticatedUser(request, userName);
            }
        } catch (Throwable e) {
            // do nothing
        }

        Application.setInPortalServer(true);

        // Set the current locale
        I18NUtil.setLocale(Application.getLanguage(request.getPortletSession()));

        if (request.getParameter(ERROR_OCCURRED) != null) {
            String errorPage = Application.getErrorPage(getPortletContext());

            if (logger.isDebugEnabled())
                logger.debug("An error has occurred, redirecting to error page: " + errorPage);

            response.setContentType("text/html");
            PortletRequestDispatcher dispatcher = getPortletContext().getRequestDispatcher(errorPage);
            dispatcher.include(request, response);
        } else {
            WebApplicationContext ctx = (WebApplicationContext) getPortletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
            AuthenticationService auth = (AuthenticationService) ctx.getBean("AuthenticationService");

            // if we have no User object in the session then an HTTP Session
            // timeout must have occured
            // use the viewId to check that we are not already on the login page
            PortletSession session = request.getPortletSession();
            String viewId = request.getParameter(VIEW_ID);
            // keep track of last view id so we can use it as return page from
            // multi-part requests
            request.getPortletSession().setAttribute(SESSION_LAST_VIEW_ID, viewId);
            User user = (User) request.getPortletSession().getAttribute(AuthenticationHelper.AUTHENTICATION_USER);
            if (user == null && (viewId == null || viewId.equals(getLoginPage()) == false)) {
                if (AuthenticationHelper.portalGuestAuthenticate(ctx, session, auth) == AuthenticationStatus.Guest) {
                    if (logger.isDebugEnabled())
                        logger.debug("Guest access successful.");

                    // perform the forward to the page processed by the Faces
                    // servlet
                    response.setContentType("text/html");
                    request.getPortletSession().setAttribute(PortletUtil.PORTLET_REQUEST_FLAG, "true");

                    // get the start location as configured by the web-client
                    // config
                    ConfigService configService = (ConfigService) ctx.getBean("webClientConfigService");
                    ClientConfigElement configElement = (ClientConfigElement) configService.getGlobalConfig().getConfigElement("client");
                    if (NavigationBean.LOCATION_MYALFRESCO.equals(configElement.getInitialLocation())) {
                        nonFacesRequest(request, response, "/jsp/dashboards/container.jsp");
                    } else {
                        nonFacesRequest(request, response, "/jsp/browse/browse.jsp");
                    }
                } else {
                    if (logger.isDebugEnabled())
                        logger.debug("No valid User login, requesting login page. ViewId: " + viewId);

                    // set last used username as special session value used by
                    // the LoginBean
                    session.setAttribute(AuthenticationHelper.SESSION_USERNAME, request.getPreferences().getValue(PREF_ALF_USERNAME, null));

                    // login page is the default portal page
                    response.setContentType("text/html");
                    request.getPortletSession().setAttribute(PortletUtil.PORTLET_REQUEST_FLAG, "true");
                    nonFacesRequest(request, response);
                }
            } else {
                if (session.getAttribute(AuthenticationHelper.SESSION_INVALIDATED) != null) {
                    // remove the username preference value as explicit logout
                    // was requested by the user
                    if (request.getPreferences().isReadOnly(PREF_ALF_USERNAME) == false) {
                        request.getPreferences().reset(PREF_ALF_USERNAME);
                    }
                    session.removeAttribute(AuthenticationHelper.SESSION_INVALIDATED);
                }

                try {
                    if (user != null) {
                        if (logger.isDebugEnabled())
                            logger.debug("Validating ticket: " + user.getTicket());

                        // setup the authentication context
                        auth.validate(user.getTicket());
                    }

                    // do the normal JSF processing
                    String loggedin = (String) getPortletContext().getAttribute("loggedin");
                    logger.debug("logged in?:" + loggedin);
                    if (loggedin != null && loggedin.equalsIgnoreCase("true")) {
                        super.facesRender(request, response);
                    } else {
                        getPortletContext().setAttribute("loggedin", "true");
                        response.setContentType("text/html");
                        request.getPortletSession().setAttribute(PortletUtil.PORTLET_REQUEST_FLAG, "true");
                        nonFacesRequest(request, response, "/jsp/browse/browse.jsp");
                    }
                } catch (AuthenticationException authErr) {
                    // ticket is no longer valid!
                    if (logger.isDebugEnabled())
                        logger.debug("Invalid ticket, requesting login page.");

                    // remove User object as it's now useless
                    request.getPortletSession().removeAttribute(AuthenticationHelper.AUTHENTICATION_USER);

                    // login page is the default portal page
                    response.setContentType("text/html");
                    request.getPortletSession().setAttribute(PortletUtil.PORTLET_REQUEST_FLAG, "true");
                    nonFacesRequest(request, response);
                } catch (Throwable e) {
                    if (getErrorPage() != null) {
                        handleError(request, response, e);
                    } else {
                        logger.warn("No error page configured, re-throwing exception");

                        if (e instanceof PortletException) {
                            throw (PortletException) e;
                        } else if (e instanceof IOException) {
                            throw (IOException) e;
                        } else {
                            throw new PortletException(e);
                        }
                    }
                }
            }
        }
    }

    /**
     * Handles errors that occur during a process action request
     */
    private void handleError(ActionRequest request, ActionResponse response, Throwable error) throws PortletException, IOException {
        // get the error bean from the session and set the error that occurred.
        PortletSession session = request.getPortletSession();
        ErrorBean errorBean = (ErrorBean) session.getAttribute(ErrorBean.ERROR_BEAN_NAME, PortletSession.PORTLET_SCOPE);
        if (errorBean == null) {
            errorBean = new ErrorBean();
            session.setAttribute(ErrorBean.ERROR_BEAN_NAME, errorBean, PortletSession.PORTLET_SCOPE);
        }
        errorBean.setLastError(error);

        response.setRenderParameter(ERROR_OCCURRED, "true");
    }

    /**
     * Handles errors that occur during a render request
     */
    private void handleError(RenderRequest request, RenderResponse response, Throwable error) throws PortletException, IOException {
        // get the error bean from the session and set the error that occurred.
        PortletSession session = request.getPortletSession();
        ErrorBean errorBean = (ErrorBean) session.getAttribute(ErrorBean.ERROR_BEAN_NAME, PortletSession.PORTLET_SCOPE);
        if (errorBean == null) {
            errorBean = new ErrorBean();
            session.setAttribute(ErrorBean.ERROR_BEAN_NAME, errorBean, PortletSession.PORTLET_SCOPE);
        }
        errorBean.setLastError(error);

        // if the faces context is available set the current view to the browse
        // page
        // so that the error page goes back to the application (rather than
        // going back
        // to the same page which just throws the error again meaning we can
        // never leave
        // the error page)
        FacesContext context = FacesContext.getCurrentInstance();
        if (context != null) {
            ViewHandler viewHandler = context.getApplication().getViewHandler();
            // TODO: configure the portlet error return page
            UIViewRoot view = viewHandler.createView(context, "/jsp/browse/browse.jsp");
            context.setViewRoot(view);
        }

        // get the error page and include that instead
        String errorPage = getErrorPage();

        if (logger.isDebugEnabled())
            logger.debug("An error has occurred, redirecting to error page: " + errorPage);

        response.setContentType("text/html");
        PortletRequestDispatcher dispatcher = getPortletContext().getRequestDispatcher(errorPage);
        dispatcher.include(request, response);
    }

    /**
     * @see org.apache.myfaces.portlet.MyFacesGenericPortlet#setDefaultViewSelector()
     */
    protected void setDefaultViewSelector() throws UnavailableException {
        super.setDefaultViewSelector();
        if (this.defaultViewSelector == null) {
            this.defaultViewSelector = new AlfrescoDefaultViewSelector();
        }
    }

    /**
     * @return Retrieves the configured login page
     */
    private String getLoginPage() {
        if (this.loginPage == null) {
            this.loginPage = Application.getLoginPage(getPortletContext());
        }

        return this.loginPage;
    }

    /**
     * @return Retrieves the configured error page
     */
    private String getErrorPage() {
        if (this.errorPage == null) {
            this.errorPage = Application.getErrorPage(getPortletContext());
        }

        return this.errorPage;
    }

    private void setAuthenticatedUser(PortletRequest req, String userName) {

        WebApplicationContext ctx = (WebApplicationContext) getPortletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
        ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
        TransactionService transactionService = serviceRegistry.getTransactionService();
        NodeService nodeService = serviceRegistry.getNodeService();

        AuthenticationComponent authComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
        AuthenticationService authService = (AuthenticationService) ctx.getBean("authenticationService");
        PersonService personService = (PersonService) ctx.getBean("personService");

        // Get a list of the available locales
        ConfigService configServiceService = (ConfigService) ctx.getBean("webClientConfigService");
        LanguagesConfigElement configElement = (LanguagesConfigElement) configServiceService.getConfig("Languages").getConfigElement(
                        LanguagesConfigElement.CONFIG_ELEMENT_ID);

        m_languages = configElement.getLanguages();

        // Set up the user information
        UserTransaction tx = transactionService.getUserTransaction();
        NodeRef homeSpaceRef = null;
        User user;
        try {
            tx.begin();
            // Set the authentication
            authComponent.setCurrentUser(userName);
            user = new User(userName, authService.getCurrentTicket(), personService.getPerson(userName));
            homeSpaceRef = (NodeRef) nodeService.getProperty(personService.getPerson(userName), ContentModel.PROP_HOMEFOLDER);
            if (homeSpaceRef == null) {
                logger.warn("Home Folder is null for user '" + userName + "', using company_home.");
                homeSpaceRef = (NodeRef) nodeService.getRootNode(Repository.getStoreRef());
            }
            user.setHomeSpaceId(homeSpaceRef.getId());
            tx.commit();
        } catch (Throwable ex) {
            logger.error(ex);

            try {
                tx.rollback();
            } catch (Exception ex2) {
                logger.error("Failed to rollback transaction", ex2);
            }

            if (ex instanceof RuntimeException) {
                throw (RuntimeException) ex;
            } else {
                throw new RuntimeException("Failed to set authenticated user", ex);
            }
        }

        // Store the user
        req.getPortletSession().setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user);
        req.getPortletSession().setAttribute(LoginBean.LOGIN_EXTERNAL_AUTH, Boolean.TRUE);

        logger.debug("...authenticated user is: " + user.getUserName() + user.getTicket());
    }

}



从上面的代码可以看出,拿去认证的用户是从Liferay的Session里拿到的当前登陆的用户,我们认为这个用户如果在alfresco里存在的话,那么也是可以访问alfresco的。这里我并没有完全整合用户认证,而是做了一个各个系统之间用户的对应关系。比如CAS的用户名和Liferay的Screen Name必须是一样的。那么从上面的代码中我们可以看到Liferay的用户的First Name必须和Alfresco的用户名一样。

更完善的三者整合是在这里: http://liferay.cignex.com/ 当然他们的方法就是中央管理了用户(LDAP)而不需要user mapping了

接下来,你只要在你的mysql里面创建一个名为alfresco的数据库,然后创建相应的用户。再start server就好了。
create database alfresco;
grant all on alfresco.* to 'alfresco'@'localhost' identified by 'alfresco' with grant option;
grant all on alfresco.* to 'alfresco'@'localhost.localdomain' identified by 'alfresco' with grant option;


所有的portlet描述文件和这个portlet-class都在附件的包里. enjoy~
分享到:
评论
1 楼 arkxu 2008-09-22  
我已经完全正和了Alfreso 3.0 beta, Lifera 5.1.1和ApacheDS 1.4.x.

commit到branch/5.3,具体请见:
http://tempo.intalio.org/tempo/branches/5.3/rsc/alfresco/

相关推荐

    Liferay跨页面Portlet之间的调用与数据传递.docx

    在Liferay中,跨页面Portlet之间的调用与数据传递是一项关键任务,因为这涉及到不同Portlet间的协作和信息共享。Liferay提供了多种通信机制,包括PortletSession、Public Render Parameters以及Portlet事件,但这些...

    Liferay-Portlet-SDK5.2.3.rar_liferay_liferay sdk_portlet

    Liferay Portlet SDK 是 Liferay Portal 平台的一个重要组成部分,它为开发者提供了构建、部署和管理portlet所需的所有工具和技术支持。Liferay Portlet SDK 5.2.3是该系列的一个特定版本,专为Liferay Portal 5.2.3...

    liferay portlet例子

    liferay portlet例子 liferay portlet例子

    Liferay5.2.3 样例Portlet

    Liferay5.2.3的样例,通过war.bat打包后发布到相应的liferay环境即可。 另外,需要配置context,tomcat中的代码如下: &lt;/Context&gt;

    Liferay portlet 工程示例代码

    Portlet有三个主要生命周期阶段:初始化、渲染和动作。初始化阶段加载portlet的配置,渲染阶段负责显示portlet内容,动作阶段处理用户提交的表单数据。 5. **Portlet开发基础** - **portlet.xml**:定义portlet的...

    liferay portlet 开发实例

    在IT领域,特别是企业级应用开发中,Liferay作为一个强大的企业门户平台,提供了丰富的功能和服务,其中Liferay Portlet的开发是构建定制化企业应用的关键技术之一。本文将基于提供的文件信息,深入解析Liferay ...

    liferay_portlet对象详解

    Portlet 技术的理解和应用是开发 Liferay 应用程序的关键。本文将深入解析 Portlet 的关键概念,包括 Portlet 请求与 URL、Portlet 模式和窗口状态。 1. Portlet 请求与 URL 在 Liferay 的 Portal 页面中,多个 ...

    liferay-spring-portlet

    通过深入学习和理解这个项目,开发者可以掌握如何在Liferay中创建和部署Spring Portlet,了解portlet的生命周期和交互方式,以及Spring框架在portlet开发中的应用。同时,如果进一步集成Hibernate,还可以学习到如何...

    liferay-portlet-development

    Liferay Plugins SDK提供了创建portlet和其他Liferay插件所需的工具和模板。安装并配置SDK后,即可开始创建自定义portlet。 ### 六、开发工具 为了提高开发效率,建议安装以下工具: - Eclipse IDE:主流的Java...

    liferay一个简单的portlet

    在Liferay中,Portlet可以通过Java API和XML配置文件来定义其行为和外观。Portlets可以是任何类型的Web应用,如新闻显示、日历、论坛等,它们能够独立工作,也可以与其他Portlets协同。 创建Liferay Portlet的过程...

    liferay-spring-mvc-portlet:Liferay Spring MVC portlet 的项目模板

    Liferay Spring Portlet MVC 使用 Maven 的 Liferay Spring Portlet MVC 项目模板。 Liferay EE 6.2.10.11 (GA1, SP710) Java 1.7 小门户 2.0 弹簧框架 4.1.5 基于注解的控制器配置 用法 $ git clone ...

    Liferay Soy Portlet可视化数据

    Liferay Soy Portlet是Liferay门户平台中一种用于创建动态用户界面的工具,它结合了模板语言Soy和JavaScript框架Dojo。Soy是Google开发的一种声明式模板语言,主要用于生成HTML,它允许开发者以清晰、简洁的方式描述...

    Liferay_Control-Panel_Portlet DTD-5.2_MVC-Portlet

    本主题主要关注Liferay中的"Control-Panel Portlet"、"DTD 5.2"以及"MVC Portlet"这三大核心概念。 首先,我们来理解"Liferay Control Panel"。控制面板是Liferay系统的核心管理界面,它提供了对站点、用户、角色、...

    liferay portlet开发

    Liferay Portlet开发中涉及到的关键配置文件主要有两个:`Portlet.xml` 和 `liferay-portlet.xml`。 - **Portlet.xml**:此文件定义了Portlet的基本属性,包括其名称、版本、依赖等信息。该文件遵循JSR 286标准,...

    Liferay集成CAS实现单点登录与应用系统集成

    Liferay是一个基于Java的企业级门户解决方案,它具备强大的portlet应用、灵活的用户管理和权限分配、以及对多种认证系统的支持,如CAS、LDAP、OpenID、OpenSSO等。CAS作为一个独立的Web应用,主要负责身份验证,确保...

    liferay portlet

    Liferay Portlet是Liferay门户平台上的核心组件,用于创建和展示交互式的Web应用程序。Portlet是portlet容器(如Liferay)中的可重用单元,它可以嵌入到门户页面上,提供各种功能,如内容展示、搜索、用户管理等。...

    Liferay Portlet 开发文档

    总的来说,这份文档是学习Liferay Portlet开发的宝典,它不仅详细介绍了Liferay的安装和配置,还包括了如何利用开发工具创建和部署Portlet的详细步骤。文档还提供了一些基础开发案例的深入解析,帮助开发者更好地...

    liferay portlet demo

    “liferay”标签明确了这是关于Liferay Portal的内容,“portlet”表示与Portlet开发相关,“demo”则意味着这是一个教学或演示性质的项目,有助于初学者上手。 【CRUDDemo-portlet】 "CRUDDemo-portlet"这个名字...

    liferay-portlet-development-guide-4.3

    《Liferay Portlet Development Guide 4.3》是针对Liferay Portal平台的一份详细开发指南,旨在帮助开发者理解和创建portlet应用程序。Liferay Portal是一个开源的企业级门户系统,它提供了丰富的功能,如用户管理、...

Global site tag (gtag.js) - Google Analytics