1.目前整合struts spring mybatis使用的pom配置(2012-3-17)
版本一不多就各种问题了,在maven库上下了不少版本,总出问题,这次配好就记下来先
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-webapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-webapp Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>3.0.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!-- struts -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-junit-plugin</artifactId>
<version>2.3.1.2</version>
</dependency>
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring integration -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.3.1.2</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.0.1</version>
</dependency>
<!-- json -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.1</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
</dependency>
</dependencies>
<build>
<finalName>my-webapp</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.log4j输出mybatis的sql语句
调试的时候这个还是很重要的,一不小心SQL就写错了
这里使用的log4j.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="java.sql" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="D:/log/web/ibatis.log" />
<param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />
<param name="Encoding" value="utf-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss} %m (%F:%L) \n\r" />
</layout>
</appender>
<logger name="java.sql">
<level value="debug" />
<appender-ref ref="java.sql" />
</logger>
<logger name="com.ibatis">
<level value="debug" />
<appender-ref ref="java.sql" />
</logger>
<root>
<priority value="error" />
<!-- <appender-ref ref="STDOUT" /> -->
</root>
</log4j:configuration>
3.struts的验证框架
struts通过validate方法验证可以自己控制错误个数,这就不说了
使用validation.xml时经常多个错误一起就出来了,如果只需要一条错误出来就得改改了
有时候xml配置的短路(short-circuit)可以解决一部分问题,解决不了也可以通过重写addFieldError来解决
public void addFieldError(String fieldName, String errorMessage) {
if (!hasFieldErrors())
super.addFieldError(fieldName, errorMessage);
}
4.struts和spring整合的问题
通过spring ioc注入配置action bean的时候,scope比较关键的,默认是单例,还有prototype等
struts本身的action就是来一次请求创建一个实例,个人感觉还是配置prototype,
有人觉得性能问题,那如果存在这个问题,struts本身为何要这样设计,舍弃性能来换取表单与成员的对应?
当然个人见解,并没有做性能对比测试.
5.使用servlet做母版页
以前学asp.net的时候就觉得母版页挺好的,很多地方都放到母版页里,去公司实习时就发现他们webx的母版页做得还不错,开发效率提高很多
回来自己考虑过,jsp可以通过继承servlet来做,在servlet里面写上basePath,写上js的引用,做cookie登录权限验证等
下面可以看下我写的两个简单的例子
public abstract class BaseJSP extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = 4035486135719535335L;
protected Logger log = Logger.getLogger(this.getClass());
private String path ;
private String basePath;
public String getPath() {
return path;
}
public String getBasePath() {
return basePath;
}
private void registerJS(HttpServletResponse resp, String src) throws IOException{
PrintWriter out = resp.getWriter();
out.write("<script type=\"text/javascript\" src=\""+src+"\"></script>\n");
}
public abstract void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException;
public boolean doMoreService(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{return true;}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
path = request.getContextPath();
basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
response.setContentType("text/html; charset=utf-8");
response.setCharacterEncoding("utf-8");
registerJS(response,basePath+"js/jquery-1.7.1.min.js");
//子类额外的服务,如果需要则重写
if(!doMoreService(request,response))
return;
//jsp的服务
this.jspService(request,response);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(req, resp);
}
public void jspService(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
_jspService(request,response);
}
}
public abstract class AuthJSP extends BaseJSP {
/**
*
*/
private static final long serialVersionUID = -5506920461926900920L;
private String username;
public String getUsername() {
return username;
}
@Override
public boolean doMoreService(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String username = CookieUtil.getCookie(req,LoginAction.LOGIN_COOKIE_NAME);
if(username==null)
{
resp.sendRedirect(getBasePath()+"account/login.jsp");
log.info("未登陆,当前JSP"+this.getClass()+"无权访问");
return false;
}
this.username = username;
return true;
}
}
然后在jsp页面继承就可以了
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" extends="com.iss.demo.servlet.AuthJSP"%>
6.maven编码和log4j编码
maven默认编译编码是gbk,如果项目编码为utf-8就容易出现乱码了(调了好久一直乱码,感谢zhao251021539帮忙解决)
pom里面加上一句
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
关于编码还可以使用属性project.build.sourceEncoding
<properties>
<project.build.sourceEncoding>GBK</project.build.sourceEncoding>
</properties>
编码属性参见
http://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#encoding
Log4j调整编码
<appender name="xxx" class="xxx">
xxx
<param name="Encoding" value="utf-8" />
xxx
</appender>
7.cookie中存入特殊字符的问题
目前版本cookie存入特殊字符会导致整个值被双引号包装,比如a===/ss就会变成"a===/ss"
通过cookie查看工具可以查看到这一变化
urlencode应该可以解决,没有去尝试
因为当前的流程简单,取值时直接将双引号去掉了
8.说两个跟SSI关系不大的
一个是查AD上用户的数字证书,可以通过用户账号与证书序列号来确定证书,本来证书序列号就可以确定,再加上用户账号可以更快的确定
private Hashtable<String, Object> env;
private Properties properties;
env = new Hashtable<String, Object>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
properties.get(Context.INITIAL_CONTEXT_FACTORY));
env.put(Context.PROVIDER_URL, properties.get(Context.PROVIDER_URL));// 链接地址
env.put(Context.SECURITY_AUTHENTICATION,
properties.get(Context.SECURITY_AUTHENTICATION));
env.put(Context.SECURITY_PRINCIPAL,
properties.get(Context.SECURITY_PRINCIPAL));// 账号
env.put(Context.SECURITY_CREDENTIALS,
properties.get(Context.SECURITY_CREDENTIALS));// 密码
public String getCert(String subjectName, String sn_base64)
throws CertificateException {
try {
DirContext ctx = new InitialDirContext(env); // 初始化上下文
SearchControls searchCons = new SearchControls(); // 搜索控件
NamingEnumeration<SearchResult> namingEnum = null;
searchCons.setSearchScope(SearchControls.SUBTREE_SCOPE);// SUBTREE_SCOPE
searchCons.setCountLimit(0);// 设置最大返回个数
searchCons.setTimeLimit(0);// 超时
// 搜索对象,第一个参数为基目录,第二个参数为fiter,fiter格式可类似于(&(CN=*)(DC=*))
namingEnum = ctx.search("CN=Users,DC=iss,DC=local", "(CN=" + subjectName + ")",
searchCons);
// 遍历搜索结果
while (namingEnum.hasMoreElements()) {
Object obj = namingEnum.nextElement();
SearchResult result = (SearchResult) obj;
// 通过属性名称获取搜索结果对象的属性值
Attribute attr = result.getAttributes().get("userCertificate");
if (attr == null)
continue;
NamingEnumeration<?> values = attr.getAll();
/*
* 获取同一个用户所拥有的所有证书,并对比序列号
*/
while (values.hasMoreElements()) {
byte[] r = (byte[]) values.next();
CertificateFactory factory = CertificateFactory
.getInstance("X.509");
ByteArrayInputStream bais = new ByteArrayInputStream(r);
X509Certificate cert = (X509Certificate) factory
.generateCertificate(bais);
byte[] serialNumberByteArray = cert.getSerialNumber()
.toByteArray();
byte[] temp = new byte[serialNumberByteArray.length];
/* CryptoAPI所获取的序列号字节数组与java获取的序列号字节数组反序,需要反转再对比 */
for (int i = serialNumberByteArray.length - 1; i >= 0; i--) {
temp[serialNumberByteArray.length - 1 - i] = serialNumberByteArray[i];
}
String serialNumberBase64 = (new sun.misc.BASE64Encoder())
.encode(temp);
if (serialNumberBase64.equals(sn_base64)) {
String certBase64 = new sun.misc.BASE64Encoder()
.encode(r);
if (certBase64.contains("\n")
|| certBase64.contains("\r"))
certBase64 = certBase64.replaceAll("[\n\r]", "");
return certBase64;
}
}
}
} catch (NamingException e) {
e.printStackTrace();
}
return "";
}
另外一个是写C++多线程时遇到对象释放的问题
个人C++菜鸟,高手包涵
线程A中创建对象Log log
传到线程B中使用,但是线程A跑完就会使得log被释放,B中就出现violation
自己解决方案是在线程B中拷贝一份,B中用完就释放,A中用完也自己释放自己的