细节问题与知识

一、tomcat7中cookie写入中文引发的异常问题及解决

问题:

Cookie cookie = new Cookie("cookieName", "Cookie值");
resp.addCookie(cookie);

目标URL访问此方法时,会抛出异常:

java.lang.IllegalArgumentException: Control character in cookie value or attribute

描述:

环境:tomcat7,Java7

具体问题:cookie写入中文会引发异常。所以这样看来Cookie默认支持的编码方式是ASCII码。不能对中文进行编码和解码。

解决方式:

创建Cookie的时候:

Cookie cookie = new Cookie(name, URLEncoder.encode(value, "UTF-8"));
读取Cookie的时候:

String value = URLDecoder.decode(cookie.getValue(), "UTF-8");

二、跳转到iframe的父窗口

在iframe子窗体跳到父窗口:

window.parent.location.href = "parent.jsp";

使用的是window的parent属性。

三、a标签disabled效果

对a标签添加 disabled="disabled" 发现不起作用。

用以下这两种方式:

1.

<a href="link.html" class="not-active">Link</a>

.not-active {
pointer-events: none;
cursor: default;
}

2.

$('a.current-page').click(function() { return false; });

四、表单标签传值问题

若为表单标签添加 disabled 属性,则该表单标签的值不会传到后台。可以使用 readonly 属性来替代 。

五、form表单中的 button 按钮

在 form 中的 button 按钮,默认 type 为 submit 类型,submit()方法为 jQuery 表单提交方法。

六、数据库:set 某个字段为 null

1.该column 不存在 not null约束,可以直接设置为null

2.该column 存在 not null约束,设置为null的时候,会设置为 对应类型的默认值。

七、css:z-index

.zIndex( zIndex ) == .css( "zIndex", zIndex )

 八、引入script标签出错

错误标签:

<script src="${ctx}/static/js/module/project/personal_center.js" type="text/javascript" charset="utf-8"/>

使用自动提示工具,补全了script标签,但是发现这样的书写是不正确的。

正确使用:

<script src="${ctx}/static/js/module/project/personal_center.js" type="text/javascript" charset="utf-8"></script>

script标签结束是以</script>作为闭合标签的。

九、get/post请求中文乱码问题

出现的问题:

通过get请求向服务器发送请求时,如果请求参数为中文时,服务器端接受到的参数为乱码。

乱码原因分析及解决办法:

1.关于解码和编码

编码:'中'→1110001

解码:1110001→'中'

乱码:编码和解码过程中使用了不同的字符集

2.Web应用中字符编码解码的问题

(1)请求过程:

<1>GET请求

浏览器端是以UTF-8进行编码,所以在服务器端也应该以UTF-8进行解码

由于GET请求参数附着在URL地址后面,所以要统一的URL地址的解码字符集。

解决办法:

在tomcat配置文件server.xml中找到第一个connector加入如下属性 URIEncoding=UTF-8

<2>POST请求

在获取请求参数前执行:request.setCharacterEncoding("UTF-8");

(2)响应过程

(1)指定响应数据的编码字符集

(2)告诉浏览器响应数据应该使用什么字符集进行解码

<1>Tomcat服务器会自动根据“解码字符集”设置“编码字符集”

<2>设置编码字符集:告诉浏览器当前响应数据的内容类型:response.setContentType("text/html;charset=UTF-8");需要注意的是,需要在response.getWriter();之前设置,否则无效。

建议:

所有的过滤器都只对POST请求起作用,在jsp页面中设置字符编码方式,都只是对表单提交时的POST请求起作用,对GET请求不能起到设置其字符编码的作用,

在GET请求中使用的是默认的编码方式,所以对GET请求,需要在server.xml文件中设置URIEncoding="UTF-8"然后重启TOMCAT便可以实现解决中文乱码问题,

但是不建议在href超链接请求中传达中文参数,也不建议在GET请求中传递中文参数

另外对传递的部分中文实现传递和接收时的统一的编码方法在传达参数时使用"reply.jsp?title="+java.net.URLEncoder.encode(keywords)

然后在接收参数页面使用keywords=new String(request.getParameter("keywords").getBytes("8859_1"));这种方式虽然暂时解决了中文乱码问题,

但是在后期的维护和部署到其他的服务器时可以仍会会出现中文乱码了问题,所以不建议使用。

对于Post请求,只需在Servlet或者jsp中写入如下代码就可以把解决从表单中传入的中文乱码问题

 request.setCharacterEncoding("utf-8");

了解:

而对于Get请求,因为请求参数会被附加到地址栏的URL之后,所以不能用上面的处理方法。应该这样:

   

String str=request.getQueryString();
//使用URLDecoder解码字符串
String str1=java.net.URLDecoder.decode(str,"utf-8");
String[] paraStrings=str1.split("&");
//paraStrings[0]就是第一个参数,依次类推...
for(String paraString : paraStrings){
String[] nameValue
=paraString.split("=");//nameValue[0]就是表单的name,nameValue[1]就是表单name对应的值 }

还有一种方法就是获取请求参数之后对请求参数值重新编码,也就是先将其转换成字节数组,再将字节数组重新解码成字符串。

String str=request.getParameter("name");
byte[] bytes=str.getBytes("ISO-8859-1");
String name=new String(bytes,"utf-8");

结论:传递中文参数时,最好使用POST请求来提交。不同服务器设置编码方式可能不同,不同操作系统设置编码方式也可能不同。

十、HttpSessionBindingListener、 HttpSessionActivationListener的意义

HttpSessionBindingListener:对象进入 session 域和从 session 域中移除

HttpSessionActivationListener:监控 Session域中的对象随 session 一起钝化和活化的变化状态

都不需要注册。

十一、idea 下 Struts2 国际化资源文件,中文编码

在 idea 下,Struts2 国际化资源中文文件不会进行自动编码,所以需要自己进行手动编码。

java提供了一个native2ascII工具用于将中文字符进行编码处理,native2ascII的用法如下所示:

十二、获取 List 泛型类型

public class Test {

    List< String>  stringList = new ArrayList< String> ();
    List< Integer>  integerList = new ArrayList< Integer> ();

    public static void main(String... args) throws Exception {
        Field stringListField = Test.class.getDeclaredField("stringList");
        ParameterizedType stringListType = (ParameterizedType) stringListField.getGenericType();
        Class< ?>  stringListClass = (Class< ?> ) stringListType.getActualTypeArguments()[0];
        System.out.println(stringListClass); // class java.lang.String.

        Field integerListField = Test.class.getDeclaredField("integerList");
        ParameterizedType integerListType = (ParameterizedType) integerListField.getGenericType();
        Class< ?>  integerListClass = (Class< ?> ) integerListType.getActualTypeArguments()[0];
        System.out.println(integerListClass); // class java.lang.Integer.
    }
}

十二、添加 jar 包到本地 maven 仓库

进入 cmd 命令行界面,切换到jar包所在目录,然后运行一下 maven 命名:

如:ckfinder-2.3.jar

mvn install:install-file -Dfile=ckfinder-2.3.jar -DgroupId=com.ckfinder -DartifactId=ckfinder -Dversion=2.3 -Dpackaging=jar -DgeneratePom=true

十三、为什么 public 修饰的方法不能实施 SpringAop 事务。

1.由于 Spring 事务管理是基于接口代理或动态字节码技术,通过 Aop 实施事务增强的。对于基于接口的 jdk 动态代理的 aop 事务增强来说,由于接口方法都必然是 public 的,

所以也就要求实现类也必须是 public 的,同时不能用 static 的修饰符。所以实施接口动态代理的方法只能是 "public" 或 "public final" 修饰的方法。

2.基于 cglib 动态代理是通过扩展被增强类,动态创建其子类的方式进行的 aop 增强。由于使用 final、static、private 修饰符的方法不能被子类覆盖,所以无法实施增强。

*3.需要特别注意的是:

(1)这些不能被 Spring 事务增强的特殊方法并非就不工作在事务环境下。只要他被外层的事务调用了,由于 spring 事务的传播行为,内部方法也可以工作在外部方法所启动的

事务上下文环境中。这里所说的不能被 spring 进行 aop 事务增强,是指这些方法不能启动事务,但是外层方法的事务上下文依旧可以顺利的传播到这些方法中。

(2)不能被 spring 增强的方法和可被 spring 增强的方法唯一区别就是可否主动启动一个事务,前者不能而后者可以。

十四、Bean 转 Map , Map 转 Bean。

1.Bean 转 Map:

(1)org.apache.commons.beanutils.BeanMap:

Person person = new Person();
person.setName("zhangsan");
person.setAge(23);

BeanMap map = new BeanMap(person);
Object name = map.get("name");
Object age = map.get("age");
System.out.println("name:" + name + ", age:" + age);

(2)自己封装:

Person p = new Person("tom", 23);
Map<String, Object> map = new HashMap<>();
Field[] fields = p.getClass().getDeclaredFields();
if(fields != null && fields.length > 0) {
    for(Field field : fields) {
        field.setAccessible(true);
        String name = field.getName();
        Object value = field.get(p);
        map.put(name, value);
    }
}

2.Map 转 Bean。

Map<String, Object> map = new HashMap<>();
map.put("age", 23);
map.put("name", "tom");
Person person = new Person();
try {
    org.apache.commons.beanutils.BeanUtils.populate(person, map);
    System.out.println(person);
} catch(IllegalAccessException e) {
    e.printStackTrace();
} catch(InvocationTargetException e) {
    e.printStackTrace();
}

十五、Propagation.NESTED 和 Propagation.REQUIRED_NEW

1.Propagation.REQUIRED_NEW

(1)propagation = Propagation.NESTED 用的是上一个事务的同一个链接,利用savepoint进行回滚。

(2)PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 "内部" 事务. 这个事务将被完 全 commited 或 rolled back 而不依赖于外部事务, 

它拥有自己的隔离范围, 自己的锁, 等等. 当内部事务开始执行时, 外部 事务将被挂起, 内务事务结束时, 外部事务将继续执行。

(3)在遇到 PROPAGATION_REQUIRES_NEW 的时候,要开启一个新的事务,需要把之前的事务挂起来,即清除和当前线程绑定的 ConnectionHolder,

然后保存起来传递给新的事务,新的事务获取新的连接,新的事务执行完毕后,再取出上述老的 ConnectionHolder 再与当前线程执行绑定。

2.Propagation.NESTED

(1)propagation = Propagation.REQUIRED_NEW 用的是上一个事务的不同链接,事务的控制完全与上一个无关。

(2)另一方面, PROPAGATION_NESTED 开始一个 "嵌套的" 事务,  它是已经存在事务的一个真正的子事务. 潜套事务开始执行时, 

它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交。

十六、Jdbc、Hibernate、Spring事务认知。

最原始的 jdbc 编程中的 Connection 职责混杂,既负责一般的 sql 操作,有负责事务操作。

Hibernate 的改进就是上述的两类功能进行分开,分别交给 Session 和 Transacation 来负责。

Spring 再进行改进就是将上述事务代码隐藏掉,以 AOP 的形式嵌套在业务代码外层,让开发者只需关心业务代码的处理。

更重要的是站在 Spring 的角度上:它根本不关心 jvm tomcat这种,它的职责就在于创建一个容器,维护容器里的 bean,如这些 bean 的依赖,这些 bean 的 Aop。

是否共享一个容器是由业务来决定的,而不是 Spring 来决定的。

十七、 NullPointException
Integer a = null;
if (a == 1) {
    System.out.println("aaa");
}

会抛出 NullPointException

十八、Intellij Idea 报错:Information:java: javacTask: 源发行版 1.8 需要目标发行版 1.8

1.选中项目,右击选择Maven-->Reimport, 再次编译。

2.setting->Compiler->Java Compiler 设置相应Module的target byte code version的合适版本就行来。

F6611014-23A1-4206-B342-E9FF8244C8C9.png

 

未完,待续。

原文地址:https://www.cnblogs.com/solverpeng/p/5631670.html