package net.wicp.tams.duckula.ops.services; import java.io.IOException; import java.util.Map; import java.util.UUID; import org.apache.tapestry5.SymbolConstants; import org.apache.tapestry5.commons.Configuration; import org.apache.tapestry5.commons.MappedConfiguration; import org.apache.tapestry5.commons.OrderedConfiguration; import org.apache.tapestry5.http.services.Request; import org.apache.tapestry5.http.services.RequestFilter; import org.apache.tapestry5.http.services.RequestHandler; import org.apache.tapestry5.http.services.Response; import org.apache.tapestry5.http.services.Session; import org.apache.tapestry5.ioc.ServiceBinder; import org.apache.tapestry5.ioc.annotations.Contribute; import org.apache.tapestry5.ioc.annotations.Local; import org.apache.tapestry5.ioc.services.ApplicationDefaults; import org.apache.tapestry5.ioc.services.SymbolProvider; import org.slf4j.Logger; import net.wicp.tams.cas.SymbolConstantsCas; import net.wicp.tams.common.Conf; import net.wicp.tams.common.jdbc.service.IProParam; import net.wicp.tams.common.thread.threadlocal.PerThreadValue; import net.wicp.tams.common.thread.threadlocal.PerthreadManager; import net.wicp.tams.component.SymbolConstantsCus; import net.wicp.tams.duckula.ops.ajax.AjaxImpl; import net.wicp.tams.duckula.ops.ajax.IAjax; import net.wicp.tams.duckula.ops.beans.SessionBean; /** * This module is automatically included as part of the Tapestry IoC Registry, * it's a good place to configure and extend Tapestry, or to place your own * service definitions. */ public class AppModule { public static void bind(ServiceBinder binder) { // binder.bind(MyServiceInterface.class, MyServiceImpl.class); // Make bind() calls on the binder object to define most IoC services. // Use service builder methods (example below) when the implementation // is provided inline, or requires more initialization than simply // invoking the constructor. binder.bind(IAjax.class, AjaxImpl.class); } public static void contributeFactoryDefaults(MappedConfiguration configuration) { // The values defined here (as factory default overrides) are themselves // overridden with application defaults by DevelopmentModule and QaModule. // The application version is primarily useful as it appears in // any exception reports (HTML or textual). configuration.override(SymbolConstants.APPLICATION_VERSION, "1.0"); // This is something that should be removed when going to production, but is // useful // in the early stages of development. configuration.override(SymbolConstants.PRODUCTION_MODE, false); //设置文件上传的目录 configuration.override(SymbolConstantsCus.PATH_FILE_UPLOAD_DIR, "abs:/data/user"); } public static void contributeApplicationDefaults(MappedConfiguration configuration) { // Contributions to ApplicationDefaults will override any contributions to // FactoryDefaults (with the same key). Here we're restricting the supported // locales to just "en" (English). As you add localised message catalogs and // other assets, // you can extend this list of locales (it's a comma separated series of locale // names; // the first locale name is the default when there's no reasonable match). configuration.add(SymbolConstants.SUPPORTED_LOCALES, "en,zh"); // You should change the passphrase immediately; the HMAC passphrase is used to // secure // the hidden field data stored in forms to encrypt and digitally sign // client-side data. configuration.add(SymbolConstants.HMAC_PASSPHRASE, "change this immediately-" + UUID.randomUUID()); //configuration.add(SymbolConstantsCas.conf_cas_db, "duckula");// 示例,需要配置全局db } /** * Use annotation or method naming convention: * contributeApplicationDefaults */ @Contribute(SymbolProvider.class) @ApplicationDefaults public static void setupEnvironment(MappedConfiguration configuration) { // Support for jQuery is new in Tapestry 5.4 and will become the only supported // option in 5.5. configuration.add(SymbolConstants.JAVASCRIPT_INFRASTRUCTURE_PROVIDER, "jquery"); configuration.add(SymbolConstants.BOOTSTRAP_ROOT, "context:mybootstrap"); } /** * This is a service definition, the service will be named "TimingFilter". The * interface, RequestFilter, is used within the RequestHandler service pipeline, * which is built from the RequestHandler service configuration. Tapestry IoC is * responsible for passing in an appropriate Logger instance. Requests for * static resources are handled at a higher level, so this filter will only be * invoked for Tapestry related requests. * * * Service builder methods are useful when the implementation is inline as an * inner class (as here) or require some other kind of special initialization. * In most cases, use the static bind() method instead. * * * If this method was named "build", then the service id would be taken from the * service interface and would be "RequestFilter". Since Tapestry already * defines a service named "RequestFilter" we use an explicit service id that we * can reference inside the contribution method. */ public RequestFilter buildTimingFilter(final Logger log) { return new RequestFilter() { public boolean service(Request request, Response response, RequestHandler handler) throws IOException { // 是否存在session PerThreadValue sessionstatusValue = PerthreadManager.getInstance() .createValue("tams:sessionstatus", Boolean.class); Session session = request.getSession(false); if (session != null) { // 把租户ID放到线程上下文中 SessionBean sessionBean = (SessionBean) session .getAttribute("sso:net.wicp.tams.duckula.ops.beans.SessionBean"); if (sessionBean != null) { sessionstatusValue.set(true); // 是不是超级管理员 PerThreadValue superUserValue = PerthreadManager.getInstance() .createValue(Conf.get("common.jdbc.sqlIntercept.superUser"), Boolean.class); superUserValue.set(sessionBean.isSuperUser()); Map colnameMapAll = IProParam.getColnameMapAll(); if (colnameMapAll.containsKey("tenant_id")) { Long tenantId = sessionBean.getTenantId(); // 删除,新增都需要这个字段,但它的key是一样的:tams:sqlIntercept:tenant_id PerThreadValue tenantValue = PerthreadManager.getInstance() .createValue(colnameMapAll.get("tenant_id"), String.class); tenantValue.set(String.valueOf(tenantId));// 去掉0,如果不区分租户则去掉tenantid字段 } if (colnameMapAll.containsKey("update_by")) { Long userId = sessionBean.getSysUser().getId(); // 删除,新增都需要这个字段,但它的key是一样的:tams:sqlIntercept:tenant_id PerThreadValue tenantValue = PerthreadManager.getInstance() .createValue(colnameMapAll.get("update_by"), String.class); tenantValue.set(String.valueOf(userId));// 0为公共资源,可以查看,但不能修改、删除 } if (colnameMapAll.containsKey("create_by")) { Long userId = sessionBean.getSysUser().getId(); // 删除,新增都需要这个字段,但它的key是一样的:tams:sqlIntercept:tenant_id PerThreadValue tenantValue = PerthreadManager.getInstance() .createValue(colnameMapAll.get("create_by"), String.class); tenantValue.set(String.valueOf(userId));// 0为公共资源,可以查看,但不能修改、删除 } } else { sessionstatusValue.set(false); } } else { sessionstatusValue.set(false); } long startTime = System.currentTimeMillis(); try { // The responsibility of a filter is to invoke the corresponding method // in the handler. When you chain multiple filters together, each filter // received a handler that is a bridge to the next filter. return handler.service(request, response); } finally { long elapsed = System.currentTimeMillis() - startTime; log.info("Request time: {} ms", elapsed); // 在这里清险上下文,否则会出现在一个调用中一个SQL拦截成功,清除后,另一个拦截失败的问题。 Map pre = Conf.getPre("common.jdbc.sqlIntercept", false); for (String key : pre.keySet()) { PerthreadManager.getInstance().cleanValue(Conf.get(key)); } PerthreadManager.getInstance().cleanValue("tams:sessionstatus"); } } }; } /** * This is a contribution to the RequestHandler service configuration. This is * how we extend Tapestry using the timing filter. A common use for this kind of * filter is transaction management or security. The @Local annotation selects * the desired service by type, but only from the same module. Without @Local, * there would be an error due to the other service(s) that implement * RequestFilter (defined in other modules). */ @Contribute(RequestHandler.class) public void addTimingFilter(OrderedConfiguration configuration, @Local RequestFilter filter) { // Each contribution to an ordered configuration has a name, When necessary, you // may // set constraints to precisely control the invocation order of the contributed // filter // within the pipeline. configuration.add("Timing", filter); } public static void contributeIgnoredPathsFilter(Configuration configuration) { configuration.add("/connector"); configuration.add("/websocket"); } // /*** // * 安装配置 // * // * @param configuration // */ // @Contribute(WebSecurityManager.class) // public static void addRealms(Configuration configuration) { // ExtendedPropertiesRealm realm = new ExtendedPropertiesRealm("classpath:shiro-users.properties"); // configuration.add(realm); // } }