*Nginx动静分离
Nginx解析图片静态资源。
注意:如果按下面方法修改后依然报这个错误,则换浏览器测试。chrome有的版本js兼容不够好。(chrome版本 43.0.2357.124 m正确)
优化:静态资源尽量不要走应用服务器,而直接走web服务器。
修改D:\javaenv\nginx-1.9.0\conf\nginx.conf(修改ngnix的conf文件)
#图片服务器
server {
listen 80;
server_name image.jt.com;
#charset koi8-r;
#access_log logs/host.access.log main;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
root c:\\jt-upload;
}
}
注意:nginx可以直接指定目录,执行image.jt.com对应服务器的c盘下的jt-upload目录。
上传完成回显图片
common.js中js的执行过程:
clickFn方法,遍历整个图片,KindEditor控件会插入一个图片的div区域,命名为pics,找到这个区域,在它下面的ul中插入li和a标签,在a标签中加入图片的链接,并设置图片大小,宽度为80,高度为50。这样用户可以看到缩略图和点击图片,浏览大图。editor.hideDialog();关闭当前的对话框窗口。
$(e).click(function(){
var form = $(this).parentsUntil("form").parent("form");
KindEditor.editor(TT.kingEditorParams).loadPlugin('multiimage',function(){
var editor = this;
editor.plugin.multiImageDialog({
clickFn : function(urlList) {
var imgArray = [];
KindEditor.each(urlList, function(i, data) {
imgArray.push(data.url);
form.find(".pics ul").append("<li><a href='"+data.url+"' target='_blank'><img src='"+data.url+"' width='80' height='50' /></a></li>");
});
form.find("[name=image]").val(imgArray.join(","));
editor.hideDialog();
}
});
});
});
常见问题
需要flash支持
添加图片是flash,通过flash调用系统的批量选择文件窗口。如果添加图片按钮无法展现,升级下flash版本。
上传失败
图片上传错误不能抛出,抛出就无法进行jsp页面回调,所以设置这个标识PicUpload.error,0表示无异常,1代表异常。
如果未设置值,回调无解解析,就会报“上传失败”错误。可以修改PicUpload设置默认值为0。这样程序中就无需设置。
浏览器兼容性
谷歌浏览器上传回显都正常,但其他浏览器IE,火狐都可能不正常;此兼容性是js组件自身问题,
不是我们代码问题。工作中遇到这样的情况,要么要求客户增加项目经费去解决js兼容问题,要
么规定客户使用什么样的浏览器,这个是现在合同中的。
Linux部署后图片无法回显
结果是正常的,http://www.jt.com/images/.../a.jpg,回显图片是要通过nginx重定向。但如果部署linux下,图片上传到linux,而之前配置的是nginx转向c:/jt-upload,当然无法回显了。需要修改代码以适应linux的环境。
域名地址测试
怎么保证开发环境的请求和真实环境的请求地址一样呢?
例如:
开发环境的URL:http://manage.jt.com/page/index
测试环境的URL:http:// 127.0.0.1:8081/page/index
这样有效避免上线后发现有些链接访问不通,或者是有些资源请求不到的问题。
那怎么样做呢?
首先域名manage.jt.com指向到127.0.0.1上,然后将端口改成80端口。
修改域名映射
修改hosts文件就可也。它没有文件后缀,实际是一个纯文本文件。
在hosts文件中增加一行:127.0.0.1 manage.jt.com
再浏览器中按域名访问http://manage.jt.com:8081/page/index,可也看到可也正确转向了。
注意不要开代理或者翻墙软件,否则可能造成不能正确转向。
工具SwitchHosts
方便修改hosts文件,并可以配置多个环境,实现环境之间快速的切换。有bug。
属性文件属性注入
扩展spring框架
- 在xml中直接引用属性文件中的内容
- 在service层通过注解方式引入配置文件内容
通过扩展spring,在service层写注解,直接读取属性值。在spring容器开启时,直接扫描注解并设置到service的属性上。注意:controller得不到值,必须在service层。因为它扩展的是spring提供的方法,service层spring管理,才可以实现,而controller是springmvc无法实现。
env.properties
REPOSITORY_PATH=c:\\jt-upload
IMAGE_BASE_URL=http://image.jt.com
ConfigAnnotationBeanPostProcessor.java
package com.jt.common.spring.exetend;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import org.springframework.beans.BeansException;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.stereotype.Service;
import org.springframework.util.ReflectionUtils;
@Service
public class ConfigAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
@Autowired
private ExtendedPropertyPlaceholderConfigurer propertyConfigurer;
private SimpleTypeConverter typeConverter = new SimpleTypeConverter();
/**
* <p>
* 通过config配置变量,bean初始化以后设置properties文件里面的值
* </p> {@inheritDoc}
*/
@Override
public boolean postProcessAfterInstantiation(final Object bean, String beanName) throws BeansException {
ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() {
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
PropertyConfig cfg = field.getAnnotation(PropertyConfig.class);
if (cfg != null) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalStateException("@PropertyConfig annotation is not supported on static fields");
}
String key = cfg.value().length() <= 0 ? field.getName() : cfg.value();
Object value = propertyConfigurer.getProperty(key);
if (cfg.required() && value == null) {
throw new NullPointerException(bean.getClass().getSimpleName() + "." + field.getName()
+ "is requred,but not been configured");
} else if (value != null) {
Object _value = typeConverter.convertIfNecessary(value, field.getType());
ReflectionUtils.makeAccessible(field);
field.set(bean, _value);
}
}
}
});
return true;
}
}
ExtendedPropertyPlaceholderConfigurer
package com.jt.common.spring.exetend;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import java.util.Properties;
public class ExtendedPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
private Properties props;
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
throws BeansException {
super.processProperties(beanFactory, props);
this.props = props;
}
public String getProperty(String key) {
return props.getProperty(key);
}
}
继承PropertyPlaceholderConfigurer类,重新了processProperties方法。
参考:http://www.cnblogs.com/dream-to-pku/p/6367396.html
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 使用spring自带的占位符替换功能,可以实现注解方式获取属性文件中的配置值 -->
<bean
class="com.jt.common.spring.exetend.ExtendedPropertyPlaceholderConfigurer">
<!-- 允许JVM参数覆盖 -->
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<!-- 忽略没有找到的资源文件 -->
<property name="ignoreResourceNotFound" value="true" />
<!-- 配置资源文件 -->
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
<value>classpath:env.properties</value>
<value>classpath:redis.properties</value>
<value>classpath:httpclient.properties</value>
<value>classpath:rabbitmq.properties</value>
</list>
</property>
</bean>
<!-- 扫描包 -->
<context:component-scan base-package="com.jt" />
<!-- 配置连接池 -->
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<!-- 数据库驱动 -->
<property name="driverClass" value="${jdbc.driver}" />
<!-- 相应驱动的jdbcUrl -->
<property name="jdbcUrl" value="${jdbc.url}" />
<!-- 数据库的用户名 -->
<property name="username" value="${jdbc.username}" />
<!-- 数据库的密码 -->
<property name="password" value="${jdbc.password}" />
<!-- 检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0 -->
<property name="idleConnectionTestPeriod" value="60" />
<!-- 连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0 -->
<property name="idleMaxAge" value="30" />
<!-- 每个分区最大的连接数 -->
<property name="maxConnectionsPerPartition" value="150" />
<!-- 每个分区最小的连接数 -->
<property name="minConnectionsPerPartition" value="5" />
</bean>
</beans>
PropertyConfig
package com.jt.common.spring.exetend;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) //自定义注解之运行时注解(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD) // //字段、枚举的常量
public @interface PropertyConfig {
String value() default "";
boolean required() default true;
}
自定义注解:
https://blog.csdn.net/github_35180164/article/details/52118286
https://blog.csdn.net/sw5131899/article/details/54947192
PropertieService
service通过自定义注解PropertyConfig注入
package com.jt.common.service;
import org.springframework.stereotype.Service;
import com.jt.common.spring.exetend.PropertyConfig;
@Service
public class PropertieService {
@PropertyConfig
public String REPOSITORY_PATH;
@PropertyConfig
public String IMAGE_BASE_URL;
}
调用代码,在service中直接注入
@PropertyConfig
private String MANAGE_URL;
@PropertyConfig
private String INDEX_AD1;
就可以直接获取属性文件中的值
env.properties
REPOSITORY_PATH=c:\\jt-upload
IMAGE_BASE_URL=http://image.jt.com
MANAGE_URL=http://manage.jt.com
INDEX_AD1=/content/query/list?categoryId=9&page=1&rows=6
INDEX_NEWS=/content/query/list?categoryId=11&page=1&rows=8
注意:必须在service中注入才能获取到。在controller中获取不到。