1. SpringMvc 局部刷新:
方法1 主要思路就是,返回的时候返回一个HTML代码片段,然后在$post的回调函数里对前端dom进行修改。
具体说来就是先新建一个jsp,如:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<c:forEach items="${blacklist}" var="blacklistitem" varStatus="status">
<tr>
<td align="left"><input type="checkbox" name="nCheckBoxId" value="${blacklistitem.blockId}" /></td>
<td align="left">${blacklistitem.resource.resourceName}</td>
<td align="left">${blacklistitem.resource.type}</td>
<td align="left">${blacklistitem.resource.size}</td>
<td align="left">${blacklistitem.blackdate}</td>
<td align="left">
<c:if test="${blacklistitem.whitedate == null}">未解封</c:if>
<c:if test="${blacklistitem.whitedate == \"\"}">未解封</c:if>
<c:if test="${blacklistitem.whitedate != null}">${blacklistitem.whitedate}</c:if>
</td>
<td align="left">${blacklistitem.reason}</td>
<td class="resourcestatus" align="left">
<c:if test="${blacklistitem.status == 1}"> 封禁中</c:if>
<c:if test="${blacklistitem.status == 0}"> 已解除</c:if>
<c:if test="${blacklistitem.status == -1}">已删除 </c:if>
</td>
</tr>
</c:forEach>
然后ModeAndView就返回这个jsp。
接下来在回调函数里:
function(data){
$('#mydata').html(data);
}
方法2 返回json,然后使用这些数据进行局部刷新。
但这种方法不太适用于使用发量数据(比如表格),会让回调函数变得很麻烦,还不如返回编译好的html代码省事(即方法一)。
但好处在于不用新建页面。这两种方法各有利弊,实际使用看情况来用了。
2. SpringMvc 返回json:
方法1 主要思路和局部刷新的方法一差不多,只是局部刷新的时候返回的时候返回一个HTML代码片段,而这里在jsp里写的是json字符串:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
{
"cpu": [${sysinfo.cpu.user},${sysinfo.cpu.nice},${sysinfo.cpu.system},${sysinfo.cpu.iowait},${sysinfo.cpu.steal},${sysinfo.cpu.idle}],
"io": [${sysinfo.io.svctm},${sysinfo.io.rrqms},${sysinfo.io.wrqms},${sysinfo.io.rs},${sysinfo.io.util}, ${sysinfo.io.await},${sysinfo.io.ws},${sysinfo.io.wsecs},${sysinfo.io.avgrqsz},${sysinfo.io.avgqusz},${sysinfo.io.rsecs}]
}
但是在这种情况下,返回的json实际上只是个字符串,在谷歌内核浏览器的调试工具能够看到Response Headers 的Content-Type的值为”text/html;charset=UTF-8”,因此需要在前端js中对传来的字符串进行解析。
这里有两种办法:
①
var json = eval('(' + str + ')'); //注意要字符串两边要有小括号,这里的作用应该是防止str含有的东西污染外边
②
var json = JSON.parse(str); //这里要注意,用这种方法需要严格遵守JSON规范,否则js绝对会报错。
方法2 使用MappingJacksonJsonView来通过ModelAndView为前端传json,这种方法不需要对串进行解析:
ModelAndView mav = new ModelAndView();
MappingJacksonJsonView view = new MappingJacksonJsonView();
Map attributes = new HashMap();
attributes.put("success", Boolean.TRUE);
attributes.put("contractNo", "contractNo");
view.setAttributesMap(attributes);
mav.setView(view);
return mav;
注:折腾这些时发现个很有意思的事情:在controller中处理路由的函数一般都返回一个ModelAndView对象,但如果你写的是返回一个字符串”xxx”,则实际这个框架回去找xxx.jsp来返回;而如果你在返回的ModelAndView对象中不指定view的话,则会去找这个路由对应的jsp文件。比如你处理的路由为/test/upload,则它会去找/test/upload.jsp。不知道是和配置文件有关还是这是该框架的特性~
3. SpringMvc 拦截器的使用:
1.在dispatcher-servlet.xml配置拦截器:
<!-- 拦截器 -->
<mvc:interceptors>
<!-- 如果要对所有请求都拦截可直接把bean写到<mvc:interceptors>下而非<mvc:interceptor>下 -->
<mvc:interceptor>
<!-- 对所有的请求拦截使用/** ,对某个模块下的请求拦截使用:/myPath/* -->
<mvc:mapping path="/**"/>
<bean class="cn.bjtu.shixun2.interceptor.AccountInterceptor">
<!-- 对于要放松判定的路由,先写到这里,稍后再程序里判断 -->
<property name="uncheckUrls">
<list>
<value>/signup</value>
<value>/login</value>
<value>/share/</value>
<value>/bower_components/</value>
<value>/css/</value>
<value>/dist/</value>
<value>/images/</value>
<value>/css/</value>
<value>/js/</value>
<value>/less/</value>
</list>
</property>
</bean>
</mvc:interceptor>
</mvc:interceptors>
2.编写AccountInterceptor类继承HandlerInterceptorAdapter :
public class AccountInterceptor extends HandlerInterceptorAdapter {
private final Logger log = Logger.getLogger(AccountInterceptor.class);
private List<String> uncheckUrls;
public List<String> getUncheckUrls() {
return uncheckUrls;
}
public void setUncheckUrls(List<String> uncheckUrls) {
this.uncheckUrls = uncheckUrls;
}
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
if ("GET".equalsIgnoreCase(request.getMethod())) {
//RequestUtil.saveRequest();
}
log.info("==============执行顺序: 1、preHandle================");
String requestUri = request.getRequestURI();
String contextPath = request.getContextPath();
String url = requestUri.substring(contextPath.length());
log.info("requestUri:"+requestUri);
log.info("contextPath:"+contextPath);
log.info("url:"+url);
//if(uncheckUrls.contains(url)) return true;
for(String uncheckUrl:uncheckUrls){
if(url.indexOf(uncheckUrl)==0) return true;
}
//TODO 做拦截的事情
if(request.getSession().getAttribute("user")==null){
log.info("Interceptor:跳转到login页面!");
response.sendRedirect(contextPath+"/login");
return false;
}
else return true;
}
/**
* 在业务处理器处理请求执行完成后,生成视图之前执行的动作
* 可在modelAndView中加入数据,比如当前时间
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
log.info("==============执行顺序: 2、postHandle================");
}
/**
* 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等
*
* 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion()
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
log.info("==============执行顺序: 3、afterCompletion================");
}
}
3. SpringMvc 获取web根目录:
1.在web.xml的节点内要有:
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>web.root</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.WebAppRootListener</listener-class>
</listener>
2.使用:
System.getProperty("web.root");
tips:java中可用System.getProperty()获取的值
参数 | 获取到的值 |
---|---|
java.versionJava | 运行时环境版本 |
java.vendor | Java 运行时环境供应商 |
java.vendor.url | Java 供应商的 URL |
java.home | Java 安装目录 |
java.vm.specification.version | Java 虚拟机规范版本 |
java.vm.specification.vendor | Java 虚拟机规范供应商 |
java.vm.specification.name | Java 虚拟机规范名称 |
java.vm.version | Java 虚拟机实现版本 |
java.vm.vendor | Java 虚拟机实现供应商 |
java.vm.name | Java 虚拟机实现名称 |
java.specification.version | Java 运行时环境规范版本 |
java.specification.vendor | Java 运行时环境规范供应商 |
java.specification.name | Java 运行时环境规范名称 |
java.class.version | Java 类格式版本号 |
java.class.path | Java 类路径 |
java.library.path | 加载库时搜索的路径列表 |
java.io.tmpdir | 默认的临时文件路径 |
java.compiler | 要使用的 JIT 编译器的名称 |
java.ext.dirs | 一个或多个扩展目录的路径 |
os.name | 操作系统的名称 |
os.arch | 操作系统的架构 |
os.version | 操作系统的版本 |
file.separator | 文件分隔符(在 UNIX 系统中是“/”) |
path.separator | 路径分隔符(在 UNIX 系统中是“:”) |
line.separator | 行分隔符(在 UNIX 系统中是“/n”) |
user.name | 用户的账户名称 |
user.home | 用户的主目录 |
user.dir | 用户的当前工作目录 |
4. SpringMvc 上传文件实现:
1.确保要有包:
commons-fileupload-x.x.jar
commons-io-x.x.jar
2.在配置文件里这么写:
<!-- fileUpload Support -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"/>
<!--max size: 10M-->
<property name="maxUploadSize" value="10485760"/>
</bean>
3.在controller里这么写:
@RequestMapping("info/upload/avatar")
public ModelAndView uploadAvatar(HttpServletRequest request, HttpServletResponse response,
@RequestParam(value = "uploadfile", required = false) MultipartFile file){
String fileName = file.getOriginalFilename();
String type = fileName.substring(fileName.lastIndexOf("."));
System.getProperty("web.root");
String filepath =
System.getProperty("web.root")
+"images"+System.getProperty("file.separator")
+"useravatar"+System.getProperty("file.separator")
+fileName+type;
File targetFile = new File(filepath);
try {
file.transferTo(targetFile);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
4.在前端这么写:
<form method="post" action="${basePath}info/upload/avatar" enctype="multipart/form-data">
<input id="lefile" name="uploadfile" type="file" onchange="validateFile()" style="display:none">
<div>
<button onclick="$('input[id=lefile]').click();">浏览</button>
<button id="upload" type="submit" class="btn btn-primary" disabled>上传</button>
</div>
</form>