关于一个错误,JSONException
JSONException 和$.post	
关于一个错误:JSONException
	1、错误的原因
		1、
			在action中存在一个属性
				private Collection<Menuitem> privilegeList;
			并且该属性有
				public Collection<Menuitem> getPrivilegeList() {
					return privilegeList;
				}
			struts2-json-plugin插件中就把上述的属性转化成json格式的对象返回到客户端			该转化是一个深度转化
			     public class Menuitem{
				  private Set<User> users;
			     }
			不仅要转化menuitem,还要转化users,在转化users时,必须保证users的数据提取出来
		2、当在dao层,发出一个hql语句"from Menuitem",这样可以把menuitem中的所有的数据加载出来,但是针对Set<User>是懒加载
		   集合中的user的数据并没有加载出来
            综述原因会包JSONException的异常
	2、解决方案
		1、因为users的数据没有提取出来,所以不加载users
			@JSON(serialize=false)
			public Set<User> getUsers() {
				return users;
			}
		2、利用迫切左外连接,在加载menuitem的时候,把user加载出来,但是必须把user中所有的引用属性设置为null,这样
		   menuitem和user就一起加载出来了
----
想获取
Action:
	public String showPrivileges() throws Exception{
		this.privilegeList = this.privilegeService.getMenuitemsByUid(this.uid);
		for(Menuitem menuitem:this.privilegeList){
			Set<User> users = menuitem.getUsers();
			for(User user:users){
				user.setDepartment(null);
				user.setPosts(null);
				user.setMenuitems(null);
			}
		}
		Thread.sleep(1000);
		return SUCCESS;
	}		   
Dao:
@Repository("privilegeDao")
public class PrivilegeDaoImpl extends CommonDaoImpl<Menuitem> implements PrivilegeDao<Menuitem>{	@Override
	public Set<Menuitem> getMenuitemsByIds(String ids) {
		// 这里要使用连接将其加载出来,但是如果前台作为这个的属性还是会报JSONException,所以还是需要将这个属性设置为null;
		return new HashSet<Menuitem>(this.hibernateTemplate.find("from Menuitem m left outer join fetch m.users u where m.mid in("+ids+")"));
	}	@Override
	public Collection<Menuitem> getMenuitemsByUid(Long uid) {
		/**
		 * 1、加载所有的权限节点
		 * 2、把用户能够访问到的节点也加载出来
		 * 3、把所有的权限节点中用户能够访问到的节点的checked设置为true
		 */
		//所有的菜单树
		Collection<Menuitem> allMenuitems = this.hibernateTemplate.find("from Menuitem");
		//用户能够访问到的菜单
		Collection<Menuitem> userMenuitems = this.hibernateTemplate.find("from Menuitem m inner join fetch m.users u where u.uid=?",uid);
		for(Menuitem menuitem:allMenuitems){
			for(Menuitem menuitem2:userMenuitems){
				//判断所有的菜单树中是否有用户能够访问到的菜单
				if(menuitem2.getMid().longValue()==menuitem.getMid().longValue()){//正在遍历的菜单项是用户能够访问到的菜单
					menuitem.setChecked(true);
				}
			}
		}
		return allMenuitems;
	}
}   上面的方式就可以将user提取出来,就是将user里面的属性设置为null;
利用迫切左外连接,在加载menuitem的时候,把user加载出来,但是必须把user中所有的引用属性设置为null,这样menuitem和user就一起加载出来了;
因为引用对象之间的加载都是懒加载;================================================
4、$.post
	1、回调函数是在服务器成功相应的时候执行的,是异步的过程
	2、$.post只能读取服务器成功响应的信息
	3、重构$.post添加错误处理功能
		1、建立struts2统一的错误处理机制
			<package name="ajax-error" namespace="/" extends="json-default">
				<global-results>
					<result name="errHandler" type="chain">
						<param name="actionName">errorProcessor</param>
					</result>
				</global-results>
				<global-exception-mappings>
					<exception-mapping exception="java.lang.Exception"
						result="errHandler" />
				</global-exception-mappings>				<action name="errorProcessor" class="com.itheima03.oa.exception.AjaxErrorProcess">
					<result type="json"></result>
				</action>
			</package>
		2、在错误处理的类中
			public class AjaxErrorProcess extends ActionSupport{
				private String message = "";
				public String getMessage() {
					return message;
				}				private Exception exception;
				public Exception getException() {
					return exception;
				}				public void setException(Exception exception) {
					this.exception = exception;
				}				public String execute() {
					/**
					 * 修改状态码
					 *    客户端就能感应到服务器端产生异常
					 */
					ServletActionContext.getResponse().setStatus(404);
					this.message = exception.getMessage();
					return SUCCESS;
				}
			}
			说明:
				message如果有空,没有异常信息,如果不为空,则有异常信息
		3、$.post方法的重构
			(function($){
			    $.oapost = function(postJSON){
				$.post(postJSON.url, postJSON.data, function(data){
					if(data.message==""){
							postJSON.callback(data);
						}else{//处理错误信息
							alert(data.message);
						}
				});
			    }
			})($);
			这样写的好处是:在一处处理了错误信息,如果想改,则修改这一个地方即可