html辨析-HTML元素的ID和Name属性的区别

大白话:html中的id属性是用来标记元素的,name属性主要是用于表单提交时传递赋值的。 

上周我也遇到了ID和Name的问题,在页面里输入了一个input type=”hidden”,只写了一个ID=’SliceInfo’,赋值后submit,在后台用Request.Params[“SliceInfo”]却怎么也去不到值。后来恍然大悟因该用Name来标示,于是在input里加了个Name=’SliceInfo’,就一切ok了。

ID就是Client端HTML元素的Identity。而Name其实要复杂的多,因为Name有很多种的用途,所以它并不能完全由ID来代替,从而将其取消掉。具体用途有:

用途1: 作为可与服务器交互数据的HTML元素的服务器端的标示,比如input、select、textarea、和button等。我们可以在服务器端根据其Name通过Request.Params取得元素提交的值。
用途2: HTML元素Input type=’radio’分组,我们知道radio button控件在同一个分组类,check操作是mutex的,同一时间只能选中一个radio,这个分组就是根据相同的Name属性来实现的。
用途3: 建立页面中的锚点,我们知道<a href=”URL”>link</a>是获得一个页面超级链接,如果不用href属性,而改用Name,如:<a name=”PageBottom”></a>,我们就获得了一个页面锚点。
用途4: 作为对象的Identity,如Applet、Object、Embed等元素。比如在Applet对象实例中,我们将使用其Name来引用该对象。
用途5: 在IMG元素和MAP元素之间关联的时候,如果要定义IMG的热点区域,需要使用其属性usemap,使usemap=”#name”(被关联的MAP元素的Name)。
用途6: 某些特定元素的属性,如attribute,meta和param。例如为Object定义参数<PARAM NAME = “appletParameter” VALUE = “value”>或Meta中<META NAME = “Author” CONTENT = “Dave Raggett”>。

 

当然HTML元素的Name属性在页面中也可以起那么一点ID的作用,因为在DHTML对象树中,我们可以使用document.getElementsByName来获取一个包含页面中所有指定Name元素的对象数组。Name属性还有一个问题,当我们动态创建可包含Name属性的元素时,不能简单的使用赋值element.name = “…”来添加其Name,而必须在创建Element时,使用document.createElement(‘<element name = “myName”></element>’)为元素添加Name属性。这是什么意思啊?看下面的例子就明白了。

<script language="JavaScript">
var input = document.createElement('INPUT');
input.id = 'myId';
input.name = 'myName';
alert(input.outerHTML);
</script>

消息框里显示的结果是:<INPUT id=myId>。

<script language="JavaScript">
var input = document.createElement('<INPUT name="myName">');
input.id = 'myId';
alert(input.outerHTML);
</script>

消息框里显示的结果是:<INPUT id=myId name=myName>。
初始化Name属性的这个设计不是IE的缺陷,因为MSDN里说了要这么做的,可是这样设计的原理什么呢?我暂时没有想太明白

另一个网友提到说:
楼主上面的方法我以前也用过,但是document.createElement(‘<INPUT name=”myName”>’);是不符合W3C规范的,在某些浏览器上被人为是错误。用setAttribute处理DOM创建的对象name属性后,用outerHTML看确实是没有name属性,但是在用form提交后name属性却有效。但是对于iframe的name属性就不行了,在提交一个target属性指向了iframe的name值的form对象后,并没有在iframe中显示,而是弹出了一个新页面。这点还希望大家想想如何去解决。是DOM代码即符合W3C规范,又适应各种浏览器。


这里再顺便说一下,要是页面中有n(n>1)个HTML元素的ID都相同了怎么办?在DHTML对象中怎么引用他们呢?如果我们使用ASPX页面,这样的情况是不容易发生的,因为aspnet进程在处理aspx页面时根本就不允许有ID非唯一,这是页面会被抛出异常而不能被正常的render。要是不是动态页面,我们硬要让ID重复那IE怎么搞呢?这个时候我们还是可以继续使用document.getElementById获取对象,只不过我们只能获取ID重复的那些对象中在HTML Render时第一个出现的对象。而这时重复的ID会在引用时自动变成一个数组,ID重复的元素按Render的顺序依次存在于数组中。

来自:http://www.cnblogs.com/birdshome/archive/2005/01/31/html_id_name.html

JQuery踩坑-jQuery中引用对象Id忘记添加#

jQuery中引用对象Id忘记添加#

//添加模态框的事件  emp_add_modal_btn
$("#emp_add_modal_btn").click(function(){
	alert("好好");
	$("empAddModal").modal({
		backdrop:"static"
	});
});

上面这个$("empAddModal")写错了,应该是$("#empAddModal")  坑爹啊 !!!

我这里用的是bootstrap框架,点击按钮,调用模态框。


在校验代码时,也忘记 # 了。        var email = $("email_add_input").val();

//2、校验邮箱信息
var email = $("email_add_input").val();
var regEmail = /^(a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
       if(!regEmail.test(email)){
		// 弹窗校验 太丑 
		//alert("邮箱格式不正确");
		//$("#email_add_input").addClass("is-invalid");
				
		show_validate_msg("#email_add_input","error","邮箱格式不正确");
		return false;
        }

 

javascript踩坑-append方法遇到字符串内部含有回车符

在网页中:JavaScript代码中,我在字符串 “页,总”内部添加了一个 回车符号,导致 无法解析字符串了 ,需要记住一下。

//解析显示分页信息
		function build_page_info(result){
			$("#page_info_area").append("当前第"+result.extend.pageInfo.pageNum+
					"页,总共"+result.extend.pageInfo.pages+"页
					,总"+result.extend.pageInfo.total+"记录")
		}

 

SSM小项目-(6)-前端交互基于ajax请求方案

一、数据交互用的是json

所以springmvc 需要导入Jackson.jar 包,这样才能返回json数据。
Maven构建的项目,操作如下:在pom.xml中添加:

<!-- 返回json字符串的支持 -->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>2.8.8</version>
</dependency>

实际加载的jar包如下:
jackson-annotations.jar
jackson-core.jar
jackson-databind.jar

二、编辑后端

消息对象:Msg.java

package com.ssm.crud.util;

import java.util.HashMap;
import java.util.Map;

/**
 * 通用的返回的类
 * 
 * @author lfy
 * 
 */
public class Msg {
	//状态码   100-成功    200-失败
	private int code;
	//提示信息
	private String msg;
	
	//返回给浏览器的数据
	private Map<String, Object> extend = new HashMap<String, Object>();

	public static Msg success(){
		Msg result = new Msg();
		result.setCode(100);
		result.setMsg("处理成功!");
		return result;
	}
	
	public static Msg fail(){
		Msg result = new Msg();
		result.setCode(200);
		result.setMsg("处理失败!");
		return result;
	}
	
	public Msg add(String key,Object value){
		this.getExtend().put(key, value);
		return this;
	}
	
	public int getCode() {
		return code;
	}

	public void setCode(int code) {
		this.code = code;
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	public Map<String, Object> getExtend() {
		return extend;
	}

	public void setExtend(Map<String, Object> extend) {
		this.extend = extend;
	}
	
	
}

EmployeeController.java

package com.ssm.crud.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ssm.crud.bean.Employee;
import com.ssm.crud.mapper.EmployeeMapper;
import com.ssm.crud.service.employeeService;
import com.ssm.crud.util.Msg;

@Controller
public class EmployeeController {

	@Autowired
	employeeService employeeService;

	@Autowired
	EmployeeMapper employeeMapper;

	@RequestMapping("/emps")
	@ResponseBody
	public Msg getEmpsWithJson(@RequestParam(value = "pn", defaultValue = "1") Integer pn, Model model) {
		
		// 引入PageHelper分页插件
		//设置返回查询结果的排序规律(字段名 排序规律)
		PageHelper.orderBy("emp_id asc");
		// 在查询之前只需要调用,传入页码,以及每页的大小
		PageHelper.startPage(pn, 5);
		// startPage后面紧跟着的这个查询操作就是一个分页查询操作
		List<Employee> emps = employeeService.getAll();

		// 使用pageInfo包装查询后的结果,只需要将pageInfo交给页面就行了。
		// 封装了详细的分页信息,包括有我们查询出来的数据,传入连续显示的页数
		PageInfo<Employee> page = new PageInfo<Employee>(emps, 5);
		
        return Msg.success().add( "pageInfo" , page);		
	}
}

三、编辑前端

index.jsp

前端首先是 加载html 标签,然后加载 JavaScript 语句
js执行过程分三步:1、加载 table 数据 2、加载分页信息  3、加载分页栏。

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport"
	content="width=device-width, initial-scale=1, shrink-to-fit=no">

<title>员工列表</title>
<%
	pageContext.setAttribute("APP_PATH", request.getContextPath());
%>
<!-- web路径:
不以/开始的相对路径,找资源,以当前资源的路径为基准,经常容易出问题。
以/开始的相对路径,找资源,以服务器的路径为标准(http://localhost:3306);需要加上项目名
		http://localhost:3306/crud
 -->
<script type="text/javascript"
	src="${APP_PATH }/static/jquery-1.12.4/jquery.js"></script>
<link
	href="${APP_PATH }/static/bootstrap-4.1.3-dist/css/bootstrap.min.css"
	rel="stylesheet">
<script
	src="${APP_PATH }/static/bootstrap-4.1.3-dist/js/bootstrap.bundle.min.js"></script>

<link
	href="${APP_PATH }/static/font-awesome-3.2.1/css/font-awesome.min.css"
	rel="stylesheet">

</head>

<body>
	<div class="container">
		<!-- 标题 -->
		<div class="col-md-12">
			<h1>SSM-CRUD</h1>
		</div>

		<!-- 按钮 -->
		<div class="row">
			<div class="col-md-4 offset-md-8">
				<button class="btn btn-primary btn-sm">
					<i class="icon-edit icon-large"></i> 编辑
				</button>
				<button class="btn btn-danger btn-sm">
					<i class="icon-trash icon-large"></i> 删除
				</button>
			</div>
		</div>

		<!-- 显示表格数据 -->
		<div class="row">
			<div class="col-md-12">
				<table class="table table-hover" id="emps_table">
					<thead>
						<tr>
							<th>#</th>
							<th>empName</th>
							<th>gender</th>
							<th>email</th>
							<th>deptName</th>
							<th>操作</th>
						</tr>
					</thead>
					<tbody>
					
					</tbody>
				</table>
			</div>
		</div>
		<!-- 显示分页信息 -->
		<div class="row">
			<div class="col-md-6" id="page_info_area"></div>
			
			<div class="col-md-6" id="page_nav_area"></div>
		</div>
	</div>

	<script type="text/javascript">
		//页面加载完成以后,直接发送ajax请求,拿到分页数据
	
		//1、页面加载完成以后,直接去发送ajax请求,要到分页数据
		$(function(){
			//去首页
			to_page(1);
		});
		
		function to_page(pn){
			$.ajax({
				url:"${APP_PATH}/emps",
				data:"pn="+pn,
				type:"GET",
				success:function(result){
					//console.log(result);
					//1、解析并显示员工数据
					build_emps_table(result);
					//2、解析并显示分页信息
					build_page_info(result);
					//3、解析显示分页条数据
					build_page_nav(result);
				}
			});
		}
		
/* 		$(function() {
			$.ajax({
				url : "${APP_PATH}/emps",
				data : "pn=1",
				type : "GET",
				success : function(result) {
					//console.log(result) 
					//1、解析并显示员工信息
					build_emps_table(result);
					//2、解析并显示分页信息
					build_page_info(result);
					//3、解析显示分页条
					build_page_nav(result);

				}
			});
		}); */

		function build_emps_table(result) {
			//清空table表格,如果不请空,下一次请求时,数据会在原来的基础上,不断添加。
			$("#emps_table tbody").empty();
			
			var emps = result.extend.pageInfo.list;
			$.each(emps, function(index, item) {
				//alert(item.empName);
				
				//构建单元格
				var empIdTd = $("<td></td>").append(item.empId);
				var empNameTd = $("<td></td>").append(item.empName);
				var genderTd = $("<td></td>").append(item.gender=='M'?"男":"女");
				var emailTd = $("<td></td>").append(item.email);
				var deptNameTd = $("<td></td>").append(item.department.deptName);				
				/**
				<button class="btn btn-primary btn-sm">
					<i class="icon-edit icon-large"></i> 编辑
				</button>
				<button class="btn btn-danger btn-sm">
					<i class="icon-trash icon-large"></i> 删除
				</button>
				**/
				var editBtn = $("<button></button>").addClass("btn btn-primary btn-sm edit-btn")
				.append($("<i></i>").addClass("icon-edit icon-large")).append(" 编辑");
                //为编辑按钮添加一个自定义的属性,来表示当前员工id
                editBtn.attr("edit-id",item.empId);
                var deleteBtn =  $("<button></button>").addClass("btn btn-danger btn-sm delete-btn")
				.append($("<i></i>").addClass("icon-trash icon-large")).append(" 删除");
                //为删除按钮添加一个自定义的属性来表示当前删除的员工id
                deleteBtn.attr("delete-id",item.empId);
                var btnTd = $("<td></td>").append(editBtn).append(" ").append(deleteBtn);

                //append方法执行完成以后还是返回原来的元素
				$("<tr></tr>")
                .append(empIdTd)
				.append(empNameTd)
				.append(genderTd)
				.append(emailTd)
				.append(deptNameTd)
				//.append(editBtn)
				//.append(deleteBtn)
				.append(btnTd)
				.appendTo("#emps_table tbody");
				
			});
		}
		
		//解析显示分页信息
		function build_page_info(result){
			//请空之前的分页显示信息,如果不请空,下一次请求时,数据会在原来的基础上,不断添加。
			$("#page_info_area").empty();
			
			$("#page_info_area").append("当前第"+result.extend.pageInfo.pageNum+
					"页,总共"+result.extend.pageInfo.pages+"页,总"+result.extend.pageInfo.total+"记录")
		}
		
		//解析显示分页条
		function build_page_nav(result) {
			//page_nav_area
			//请空之前的分页条,如果不请空,下一次请求时,数据会在原来的基础上,不断添加。
			$("#page_nav_area").empty();
			
			var ul = $("<ul></ul>").addClass("pagination");
			
			//构建元素
			var firstPageLi = $("<li></li>").addClass("page-item").append(  $("<a></a>").addClass("page-link").attr("href","#").append("首页")  );
			var prePageLi = $("<li></li>").addClass("page-item").append(  $("<a></a>").addClass("page-link").append("&laquo;")  );
		
			var lastPageLi = $("<li></li>").addClass("page-item").append(  $("<a></a>").addClass("page-link").attr("href","#").append("末页")   );
			var nextPageLi = $("<li></li>").addClass("page-item").append(  $("<a></a>").addClass("page-link").append("&raquo;")   );

			//添加首页和前一页 的提示
			ul.append(firstPageLi).append(prePageLi);
			if(result.extend.pageInfo.hasPreviousPage == false){
				firstPageLi.addClass("disabled");
				prePageLi.addClass("disabled");
			}else{
				//为元素添加点击翻页的事件
				firstPageLi.click(function(){
					to_page(1);
				});
				prePageLi.click(function(){
					to_page(result.extend.pageInfo.pageNum -1);
				});
			}
			
			//遍历页码号1,2,3等,给ul中添加页码提示
			$.each(result.extend.pageInfo.navigatepageNums,function(index,item){
				var numLi = $("<li></li>").addClass("page-item").append(  $("<a></a>").addClass("page-link").append(item)  );
				if(result.extend.pageInfo.pageNum == item){
					numLi.addClass("active");
				}
				
				numLi.click(function(){
					to_page(item);
				});
				
				ul.append(numLi);
			})
			
			//添加下一页和末页 的提示
			ul.append(nextPageLi).append(lastPageLi);
			if(result.extend.pageInfo.hasNextPage == false){
				nextPageLi.addClass("disabled");
				lastPageLi.addClass("disabled");
			}else{
				nextPageLi.click(function(){
					to_page(result.extend.pageInfo.pageNum +1);
				});
				lastPageLi.click(function(){
					to_page(result.extend.pageInfo.pages);
				});
			}
			
			//把ul加入到nav
			var navEle = $("<nav></nav>").append(ul);
			navEle.appendTo("#page_nav_area");
		}
	</script>

</body>
</html>

 

 

SSM小项目-(5)-前端交互基于http请求方案

一、后端数据接口

EmployeeController.java

package com.ssm.crud.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ssm.crud.bean.Employee;
import com.ssm.crud.mapper.EmployeeMapper;
import com.ssm.crud.service.employeeService;

@Controller
public class EmployeeController {

	@Autowired 
	employeeService employeeService;
	
	@Autowired
	EmployeeMapper employeeMapper;
	
	/**
	 * 查询员工数据(分页查询)
	 * 
	 * @return
	 */
	@RequestMapping("/emps")
	public String getEmps( @RequestParam(value = "pn", defaultValue = "1") Integer pn, Model model) {
		
                // 引入PageHelper分页插件
		//设置返回查询结果的排序规律(字段名 排序规律)
		PageHelper.orderBy("emp_id asc");
		// 在查询之前只需要调用,传入页码,以及每页的大小
		PageHelper.startPage(pn, 5);
		// startPage后面紧跟着的这个查询操作就是一个分页查询操作
		List<Employee> emps = employeeService.getAll();
		
		
		// 使用pageInfo包装查询后的结果,只需要将pageInfo交给页面就行了。
		// 封装了详细的分页信息,包括有我们查询出来的数据,传入连续显示的页数
		PageInfo page = new PageInfo(emps, 5);
                //设置返回查询结果的排序规律(字段名 排序规律)
		PageHelper.orderBy("emp_id asc");

		model.addAttribute("pageInfo", page);

		/*****  一开始 EmployeeService 方法中 居然 返回的 null,忘记修改了 坑爹的教训啊 
		System.out.println("当前页码:"+page.getPageNum());
		System.out.println("总记录数:"+page.getTotal());
		System.out.println("每页的记录数:"+page.getPageSize());
		System.out.println("总页码:"+page.getPages());
		System.out.println("是否第一页:"+page.isIsFirstPage());
		System.out.println("连续显示的页码:");
		int[] nums = page.getNavigatepageNums();
		for (int i = 0; i < nums.length; i++) {
			System.out.println(nums[i]);
		}	
		******/
		return "list";
	}
	
}

从上面的数据接口我们可以看出,当http请求比如   /emp?pn=2    就能返回需要的信息了。  

二、编写结果返回页

请求地址:http://localhost:8080/ssm.crud/emps

结果返回:list.jsp  【因为是转发,不会显示结果页的url路径】

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport"
	content="width=device-width, initial-scale=1, shrink-to-fit=no">

<title>员工列表</title>
<%
	pageContext.setAttribute("APP_PATH", request.getContextPath());
%>
<!-- web路径:
不以/开始的相对路径,找资源,以当前资源的路径为基准,经常容易出问题。
以/开始的相对路径,找资源,以服务器的路径为标准(http://localhost:8080);需要加上项目名
		http://localhost:8080/ssm.crud
 -->
<script type="text/javascript"
	src="${APP_PATH }/static/jquery-1.12.4/jquery.js"></script>
<link
	href="${APP_PATH }/static/bootstrap-4.1.3-dist/css/bootstrap.min.css"
	rel="stylesheet">
<script
	src="${APP_PATH }/static/bootstrap-4.1.3-dist/js/bootstrap.bundle.min.js"></script>

<link
	href="${APP_PATH }/static/font-awesome-3.2.1/css/font-awesome.min.css"
	rel="stylesheet">

</head>

<body>
	<div class="container">
		<!-- 标题 -->
		<div class="col-md-12">
			<h1>SSM-CRUD</h1>
		</div>

		<!-- 按钮 -->
		<div class="row">
			<div class="col-md-4 offset-md-8">
				<button class="btn btn-primary btn-sm">
					<i class="icon-edit icon-large"></i> 编辑
				</button>
				<button class="btn btn-danger btn-sm">
					<i class="icon-trash icon-large"></i> 删除
				</button>
			</div>
		</div>

		<!-- 显示表格数据 -->
		<div class="row">
			<div class="col-md-12">
				<table class="table table-hover">
					<tr>
						<th>#</th>
						<th>empName</th>
						<th>gender</th>
						<th>email</th>
						<th>deptName</th>
						<th>操作</th>
					</tr>
					<c:forEach items="${pageInfo.list}" var="emp">
						<tr>
							<th>${emp.empId}</th>
							<th>${emp.empName }</th>
							<th>${emp.gender == "M" ? "男" : "女"}</th>
							<th>${emp.email}</th>
							<th>${emp.department.deptName}</th>
							<th>
								<button class="btn btn-primary btn-sm">
									<i class="icon-edit icon-large"></i> 编辑
								</button>
								<button class="btn btn-danger btn-sm">
									<i class="icon-trash icon-large"></i> 删除
								</button>
							</th>
						</tr>
					</c:forEach>
				</table>
			</div>
		</div>
		<!-- 显示分页信息 -->
		<div class="row">
			<div class="col-md-6">
				当前第${pageInfo.pageNum}页,总共有${pageInfo.pages}页,总共有${pageInfo.total}记录。
			</div>


			<div class="col-md-6">
				<nav aria-label="Page navigation example">
				<ul class="pagination">
					<li class="page-item"><a class="page-link"
						href="${APP_PATH}/emps?pn=1">首页</a></li>

					<c:if test="${pageInfo.hasPreviousPage}">
						<li class="page-item"><a class="page-link"
							href="${APP_PATH}/emps?pn=${pageInfo.pageNum-1}"
							aria-label="Previous"> <span aria-hidden="true">&laquo;</span><span
								class="sr-only">Previous</span></a></li>
					</c:if>
					<!-- jstl 标签 获取的都是用 .属性  不能用 get属性方法,否则会报错-->
					<c:forEach items="${pageInfo.navigatepageNums}" var="page_Num">
						<c:choose>
							<c:when test="${pageInfo.pageNum == page_Num }">
								<li class="page-item active"><a class="page-link" href="#">${page_Num}</a></li>
							</c:when>
							<c:otherwise>
								<li class="page-item"><a class="page-link"
									href="${APP_PATH}/emps?pn=${page_Num}">${page_Num}</a></li>
							</c:otherwise>
						</c:choose>
					</c:forEach>

					<c:if test="${pageInfo.hasNextPage}">
						<li class="page-item"><a class="page-link"
							href="${APP_PATH}/emps?pn=${pageInfo.pageNum+1}"
							aria-label="Next"> <span aria-hidden="true">&raquo;</span> <span
								class="sr-only">Next</span>
						</a></li>
					</c:if>
					<li class="page-item"><a class="page-link"
						href="${APP_PATH}/emps?pn=${pageInfo.pages }">末页</a></li>
				</ul>
				</nav>
			</div>
		</div>
	</div>


</body>
</html>

 

SSM小项目-(4)-搭建Bootstrap前端框架

前端框架搭建

一、下载bootsrap框架

本项目采用的是V4版本,V4版本和V3有点不同,V4版本移除了图库。所以我们需要自己导入其他图库。

Bootstrap框架需要 jQuery.js,同时V4版本还需要 Popper.js。Our bootstrap.bundle.js and bootstrap.bundle.min.js include Popper, but not jQuery.

下载 Bootstrap 后,我们可以看到只有两个文件夹,一个是 js文件夹,一个是css文件夹。使用时只需要引入:JQuery.js , bootstrap.bundle.min.js,bootstrap.min.css就可以了。

二、下载图标

Bootstrap doesn’t include an icon library by default, but we have a handful of recommendations for you to choose from. While most icon sets include multiple file formats, we prefer SVG implementations for their improved accessibility and vector support.

Preferred

We’ve tested and used these icon sets ourselves.

More options

While we haven’t tried these out, they do look promising and provide multiple formats—including SVG.

这里以  Font Awesome 举例,此处代码下载 ,此处使用说明 。
Font Awesome 总结来说:就是将下载好的 font 文件夹 拿出来,并从 css 文件夹中拿出 font-awesome.min.css 将这两个拿到 web项目中,并且在  font-awesome.min.css中编辑 font文件夹 所在路径。使用时,只需要引入 font-awesome.min.css 就行了。

我用的是 3.0版本的 Font Awesome,此处下载代码 ,框架引用方式和最新版的相同。只是在代码使用上有所不同:
3.0版本  <i class="icon-camera-retro"></i> 调用照相机图标。
5.4版本 <i class="fas fa-ghost"></i> 调用幽灵图标。

The fa prefix has been deprecated in version 5. The new default is the fas solid style and the fabstyle for brands.

三、前端框架整合概览

四、编写测试网页

index.jsp

[请求地址:http://localhost:8080/ssm.crud/index.jsp]

<%@ page language="java" import="java.util.*"
	contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Bootstrap 概述</title>
<%
	pageContext.setAttribute("APP_PATH", request.getContextPath());
%>
<!-- web路径:
不以/开始的相对路径,找资源,以当前资源的路径为基准,经常容易出问题。
以/开始的相对路径,找资源,以服务器的路径为标准(http://localhost:8080);需要加上项目名
		http://localhost:8080/crud
 -->
<script type="text/javascript"
	src="${APP_PATH }/static/jquery-1.12.4/jquery.js"></script>
<link
	href="${APP_PATH }/static/bootstrap-4.1.3-dist/css/bootstrap.min.css"
	rel="stylesheet">
<script
	src="${APP_PATH }/static/bootstrap-4.1.3-dist/js/bootstrap.bundle.min.js"></script>

<link
	href="${APP_PATH }/static/font-awesome-3.2.1/css/font-awesome.min.css"
	rel="stylesheet">

</head>
<body>
	<%
		/***  一开始,不写注释,想靠 <!-- -->将jsp跳转标签注释掉,发现没有效果啊,坑爹
		<!-- 
		<jsp:forward page="/emps"></jsp:forward>   
		--> ***/
	%>

	<div class="container">

		<!-- 标题 -->
		<div class="col-md-12">
			<h1>Bootstrap 是行列式布局 ,一行有12列。</h1>
		</div>

		<!-- 按钮 -->
		<div class="row">
			<!-- 布局占了4列,偏移8列 -->
			<div class="col-md-4 offset-md-8 ">
				<div class="bg-info">
					<h5>测试偏移</h5>
				</div>
			</div>
		</div>

		<hr />

		<nav class="navbar navbar-expand-lg navbar-light bg-light"> <a
			class="navbar-brand" href="#">Navbar</a>
		<button class="navbar-toggler" type="button" data-toggle="collapse"
			data-target="#navbarSupportedContent"
			aria-controls="navbarSupportedContent" aria-expanded="false"
			aria-label="Toggle navigation">
			<span class="navbar-toggler-icon"></span>
		</button>

		<div class="collapse navbar-collapse" id="navbarSupportedContent">
			<ul class="navbar-nav mr-auto">
				<li class="nav-item active"><a class="nav-link" href="#">Home
						<span class="sr-only">(current)</span>
				</a></li>
				<li class="nav-item"><a class="nav-link" href="#">Link</a></li>
				<li class="nav-item dropdown"><a
					class="nav-link dropdown-toggle" href="#" id="navbarDropdown"
					role="button" data-toggle="dropdown" aria-haspopup="true"
					aria-expanded="false"> Dropdown </a>
					<div class="dropdown-menu" aria-labelledby="navbarDropdown">
						<a class="dropdown-item" href="#">Action</a> <a
							class="dropdown-item" href="#">Another action</a>
						<div class="dropdown-divider"></div>
						<a class="dropdown-item" href="#">Something else here</a>
					</div></li>
				<li class="nav-item"><a class="nav-link disabled" href="#">Disabled</a>
				</li>
			</ul>
			<form class="form-inline my-2 my-lg-0">
				<input class="form-control mr-sm-2" type="search"
					placeholder="Search" aria-label="Search">
				<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
			</form>
		</div>
		</nav>

		<hr />

		<div>
			<h6>右对齐的关键属性是==> margin-left:auto 这样子浏览器会尽可能增加右边距离</h6>
		</div>

		<hr />

		<div class="row">
			<!-- 右对齐的方式,利用了 ml-auto ==> margin-left:auto ,
		     这样子浏览器解析的时候,会尽可能的让布局多占空间的,所以变成右对齐了
		     mr-3 ==> margin-right:3*bootstrap的基本单位。
		     mx-auto ==>代表这个单位对左右两边的距离都是自动的,这个单位在父类看来是居中的。
		      -->
			<div class="ml-auto mr-3">
				<!-- 按钮样式,直接加类就行 -->
				<button class="btn btn-primary btn-sm ">
					<!-- 图标是加载了 font-awesome 的 -->
					<i class="icon-edit icon-large"></i> 编辑
				</button>
				<button class="btn btn-danger btn-sm ">
					<i class="icon-trash icon-large"></i> 删除
				</button>
			</div>


		</div>
		<hr />

		<div class="row">
            <!-- text-center 代表在本对象看来, 自己内部对象是居中的 -->
			<div class="col-md-12  text-center">
				<h5>
					所有的布局组件:如按钮,表单,表格,分页等组件,都有demo,可以直接复制粘贴拿来 <span
						class="badge badge-secondary">修改使用</span>
				</h5>
			</div>

		</div>


		<table class="table table-striped  table-hover">
			<thead>
				<tr>
					<th scope="col">#</th>
					<th scope="col">First</th>
					<th scope="col">Last</th>
					<th scope="col">Handle</th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<th scope="row">1</th>
					<td>Mark</td>
					<td>Otto</td>
					<td>@mdo</td>
				</tr>
				<tr>
					<th scope="row">2</th>
					<td>Jacob</td>
					<td>Thornton</td>
					<td>@fat</td>
				</tr>
				<tr>
					<th scope="row">3</th>
					<td>Mark</td>
					<td>Otto</td>
					<td>@mdo</td>
				</tr>
			</tbody>
		</table>


		<nav aria-label="Page navigation example">
		<ul class="pagination justify-content-end">
			<li class="page-item disabled"><a class="page-link" href="#"
				tabindex="-1">Previous</a></li>
			<li class="page-item"><a class="page-link" href="#">1</a></li>
			<li class="page-item"><a class="page-link" href="#">2</a></li>
			<li class="page-item"><a class="page-link" href="#">3</a></li>
			<li class="page-item"><a class="page-link" href="#">Next</a></li>
		</ul>
	</div>

	<hr />


	<div class="row">

		<div class="col-md-8 mx-auto">
			<div class="bg-info text-center">
				<p >表单对象的校验,首先只要给form对象 添加 was-validated 属性就行,
				此时表单会根据 input的type属性,自动校验,比如是否为空,比如type=email,那么会检查是否是email。
				这些是bootstrap,自己添加的。一般我们不用,我们自己校验,判断 input 合法吧,
				并给input标签 添加 is-invalid 或 is-valid 属性,来表示是否合法。
				表单中的:valid-feedback 和 invalid-feedback 是用来 展示校验结果信息的
				</p>
			</div>
			
			
			<div>
			<form class="needs-validation" novalidate>
			<div class="form-row">
				<div class="col-md-4 mb-3">
					<label for="validationCustom01">First name</label> <input
						type="text" class="form-control" id="validationCustom01"
						placeholder="First name" value="Mark" required>
					<div class="valid-feedback">Looks good!</div>
				</div>
				<div class="col-md-4 mb-3">
					<label for="validationCustom02">Last name</label> <input
						type="text" class="form-control" id="validationCustom02"
						placeholder="Last name" value="Otto" required>
					<div class="valid-feedback">Looks good!</div>
				</div>
				<div class="col-md-4 mb-3">
					<label for="validationCustomUsername">Username</label>
					<div class="input-group">
						<div class="input-group-prepend">
							<span class="input-group-text" id="inputGroupPrepend">@</span>
						</div>
						<input type="text" class="form-control"
							id="validationCustomUsername" placeholder="Username"
							aria-describedby="inputGroupPrepend" required>
						<div class="invalid-feedback">Please choose a username.</div>
					</div>
				</div>
			</div>
			<div class="form-row">
				<div class="col-md-6 mb-3">
					<label for="validationCustom03">City</label> <input type="text"
						class="form-control" id="validationCustom03" placeholder="City"
						required>
					<div class="invalid-feedback">Please provide a valid city.</div>
				</div>
				<div class="col-md-3 mb-3">
					<label for="validationCustom04">State</label> <input type="text"
						class="form-control" id="validationCustom04" placeholder="State"
						required>
					<div class="invalid-feedback">Please provide a valid state.</div>
				</div>
				<div class="col-md-3 mb-3">
					<label for="validationCustom05">Zip</label> <input type="text"
						class="form-control" id="validationCustom05" placeholder="Zip"
						required>
					<div class="invalid-feedback">Please provide a valid zip.</div>
				</div>
			</div>
			<div class="form-group">
				<div class="form-check">
					<input class="form-check-input" type="checkbox" value=""
						id="invalidCheck" required> <label
						class="form-check-label" for="invalidCheck"> Agree to
						terms and conditions </label>
					<div class="invalid-feedback">You must agree before
						submitting.</div>
				</div>
			</div>
			<button class="btn btn-primary" type="submit">Submit form</button>
		</form>
			
			</div>
		</div>
	
	</div>
	
	
	<script>
		// Example starter JavaScript for disabling form submissions if there are invalid fields
		(function() {
			'use strict';
			window.addEventListener('load',
					function() {
						// Fetch all the forms we want to apply custom Bootstrap validation styles to
						var forms = document
								.getElementsByClassName('needs-validation');
						// Loop over them and prevent submission
						var validation = Array.prototype.filter.call(forms,
								function(form) {
									form.addEventListener('submit', function(
											event) {
										if (form.checkValidity() === false) {
											event.preventDefault();
											event.stopPropagation();
										}
										form.classList.add('was-validated');
									}, false);
								});
					}, false);
		})();
	</script>

</body>
</html>

 

 

SSM小项目-(3)-模拟网页请求进行后端单元测试

一、加载log4j框架,方便调试

前面的文章已经将SSM环境搭建好了,我们现在开始写过网页,测试一下。
为了测试方便:我们加载log4j框架,用于查看错误日志。【框架需要jar包和配置文件】

pom.xml中配置:

<!-- 这个是 最新版2.x 和 1.x 版本 的配置文件 不兼容 https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core 
	<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> 
	<version>2.11.1</version> </dependency> -->
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>

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="STDOUT" class="org.apache.log4j.ConsoleAppender">
   <param name="Encoding" value="UTF-8" />
   <layout class="org.apache.log4j.PatternLayout">
    <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m  (%F:%L) \n" />
   </layout>
 </appender>
 <logger name="java.sql">
   <level value="debug" />
 </logger>
 <logger name="org.apache.ibatis">
   <level value="info" />
 </logger>
 <root>
   <level value="debug" />
   <appender-ref ref="STDOUT" />
 </root>
</log4j:configuration>

web工程,只要放在项目根目录就行了,目的是打包后在class文件的根目录中,这样就能自动加载了。如果不想自动加载,则可以将配置文件改个名或者移动到其他目录,并在代码中指明 log4j配置文件 的路径。参看java工具-log4j框架-基本介绍和文件配置及框架加载调用

二、编写测试请求页

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<jsp:forward page="/emps"></jsp:forward>

一开始写错成了:jsp:fowward 导致报错Invalid standard action 要注意了啊。

三、编写请求处理

EmployeeController.java

package com.ssm.crud.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ssm.crud.bean.Employee;
import com.ssm.crud.mapper.EmployeeMapper;
import com.ssm.crud.service.employeeService;

@Controller
public class EmployeeController {

	@Autowired 
	employeeService employeeService;
	
	@Autowired
	EmployeeMapper employeeMapper;
	
	/**
	 * 查询员工数据(分页查询)
	 * 
	 * @return
	 */
	@RequestMapping("/emps")
	public String getEmps( @RequestParam(value = "pn", defaultValue = "1") Integer pn, Model model) {
		// 这不是一个分页查询;
		// 引入PageHelper分页插件
		// 在查询之前只需要调用,传入页码,以及每页的大小
		PageHelper.startPage(pn, 5);
		// startPage后面紧跟的这个查询就是一个分页查询
		List<Employee> emps = employeeService.getAll();
		
		
		// 使用pageInfo包装查询后的结果,只需要将pageInfo交给页面就行了。
		// 封装了详细的分页信息,包括有我们查询出来的数据,传入连续显示的页数
		PageInfo page = new PageInfo(emps, 5);
		model.addAttribute("pageInfo", page);

		/*****  一开始 EmployeeService 方法中 居然 返回的 null,忘记修改了 坑爹的教训啊 
		System.out.println("当前页码:"+page.getPageNum());
		System.out.println("总记录数:"+page.getTotal());
		System.out.println("每页的记录数:"+page.getPageSize());
		System.out.println("总页码:"+page.getPages());
		System.out.println("是否第一页:"+page.isIsFirstPage());
		System.out.println("连续显示的页码:");
		int[] nums = page.getNavigatepageNums();
		for (int i = 0; i < nums.length; i++) {
			System.out.println(nums[i]);
		}	
		******/
		return "list";
	}
	
}

EmployeeService.java

package com.ssm.crud.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ssm.crud.bean.Employee;
import com.ssm.crud.mapper.EmployeeMapper;

@Service
public class employeeService {

	@Autowired
	EmployeeMapper employeeMapper;
	
	public  List<Employee> getAll() {
                // 这个地方坑爹啊,一开始 返回了 null,忘记把 结果返回了
		return employeeMapper.selectByExampleWithDept(null);
		
	}

}

四、编写结果返回页

list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>员工列表</title>
</head>
<body>

</body>
</html>

五、模拟网页请求的单元测试

在测试当中,会遇到 校验错误:

INFO  10-13 15:56:27,762 HV000001: Hibernate Validator 5.4.1.Final  (Version.java:30) 
DEBUG 10-13 15:56:27,785 Cannot find javax.persistence.Persistence on classpath. Assuming non JPA 2 environment. All properties will per default be traversable.  (DefaultTraversableResolver.java:70) 
DEBUG 10-13 15:56:27,796 Failed to set up a Bean Validation provider  (OptionalValidatorFactoryBean.java:43) 
javax.validation.ValidationException: HV000183: Unable to initialize 'javax.el.ExpressionFactory'. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead
	at 
。。。。。。
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.NoClassDefFoundError: javax/el/ExpressionFactory
	at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.buildExpressionFactory(ResourceBundleMessageInterpolator.java:98)
	... 46 more

看log日志,是缺少 el jar包,于是在pom中添加

<dependency>
	<groupId>javax.el</groupId>
	<artifactId>el-api</artifactId>
	<version>2.2</version>
	<scope>provided</scope>
</dependency>

<dependency>
	<groupId>org.glassfish.web</groupId>
	<artifactId>el-impl</artifactId>
	<version>2.2</version>
	<scope>test</scope>
</dependency>

Juint单元测试:【勘误,现在回来重新说明一下:maven的web工程的网页和资源应该放在webapp目录下,所以下面的file:WebContent/WEB-INF/springMVC-servlet.xml 应该替换成 file:src/main/webapp/WEB-INF/springMVC-servlet.xml

package com.ssm.crud.test;

import static org.junit.Assert.*;

import java.util.List;

import org.apache.log4j.xml.DOMConfigurator;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import com.github.pagehelper.PageInfo;
import com.ssm.crud.bean.Employee;

/**
 * 使用Spring测试模块提供的测试请求功能,测试curd请求的正确性 Spring4测试的时候,需要servlet3.0的支持
 * 
 * @author lfy
 *    当我构建好Maven的web项目时,我发现 有两个 放 web 文件的 地方,我选择将网页文件放在 WebContent 文件夹中
 *    file:WebContent/WEB-INF/springMVC-servlet.xml 【WebContent下面有网页文件】
 *    file:src/main/webapp/WEB-INF/springMVC-servlet.xml 【src/main/webapp下面什么文件都没有】
 */

//@RunWith这个是 junit-4.jar包 提供的注解, 而 SpringJUnit4ClassRunner.class 是spring-test 提供的类
@RunWith(SpringJUnit4ClassRunner.class)
//@WebAppConfiguration  这个是 spring-test.jar包 提供的注解, 用于根据 web.xml的配置,注入 SpringMVC 容器,使SpringMVC容器不需要创建 ,直接获取就行。
@WebAppConfiguration
//@ContextConfiguration 这个是 spring-test.jar包 提供的注解 , 用于启动 spring容器,方便直接获取spring容器中的bean
@ContextConfiguration(locations = { "classpath:springIOC.xml", "file:WebContent/WEB-INF/springMVC-servlet.xml" })
public class SpringMVCTest {

	
	@Autowired// 传入Springmvc的ioc,因为容器内部的bean可以自动注入,但SpringMVC这个容器不是springIOC中的bean,无法自动注入,所以需要在类前面添加 @WebAppConfiguration ,根据web.xml配置 来注入SpringMVC容器
	WebApplicationContext context;
	
	// 虚拟mvc请求,获取到处理结果。
	MockMvc mockMvc;

	@Before // 表示 每次调用 http请求 都要初始化一下
	public void initMokcMvc() {
		mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
	}

	@Test
	public void testPage() throws Exception {
		
 
		// 模拟请求拿到返回值
		MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/emps").param("pn", "3")).andReturn();

		// 请求成功以后,请求域中会有pageInfo;我们可以取出pageInfo进行验证

		MockHttpServletRequest request = result.getRequest();
		PageInfo pi = (PageInfo) request.getAttribute("pageInfo");
		System.out.println("当前页码:" + pi.getPageNum());
		System.out.println("总页码:" + pi.getPages());
		System.out.println("总记录数:" + pi.getTotal());
		System.out.println("在页面需要连续显示的页码");
		int[] nums = pi.getNavigatepageNums();
		for (int i : nums) {
			System.out.println(" " + i);
		}

		// 获取员工数据
		List<Employee> list = pi.getList();
		for (Employee employee : list) {
			System.out.println("ID:" + employee.getEmpId() + "==>Name:" + employee.getEmpName());
		}

	}

}

六、当前项目概览

经过后面的测试验证,网页文件放在WebContent目录下是对的,已在服务器上运行成功。(勘误,上面的蓝色字是之前学习时记录的,现在回来勘误,其实不应该放在WebContent目录中,项目第一章配置环境时已经重新说明过了,maven的web工程的网页和资源应该放在webapp目录下)

springmvc踩坑-service文件没有标注且返回值null

在我们自动新建一个服务类时,因为方便,有时会忘记给类添加 @Service注解

甚至忘记 将返回值 添加好。

package com.ssm.crud.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ssm.crud.bean.Employee;
import com.ssm.crud.mapper.EmployeeMapper;

@Service
public class employeeService {

	@Autowired
	EmployeeMapper employeeMapper;
	
	public  List<Employee> getAll() {
        employeeMapper.selectByExampleWithDept(null);
		return null;
	}//上面这个地方 的返回值 默认是null  而我们需要的操作是 return  employeeMapper.selectByExampleWithDept(null);


}

 

mybatis踩坑-IncompleteElementException

org.apache.ibatis.builder.IncompleteElementException: Could not find SQL statement to include with refid ‘com.ssm.crud.mapper.EmployeeMapper.WithDept_Column_List

at org.apache.ibatis.builder.xml.XMLIncludeTransformer.findSqlFragment(XMLIncludeTransformer.java:90)

这句话报错的意思是,sql映射文件中:没有定义说明 WithDept_Column_List语句的含义。比如在下面的配置文件中:SQL标签的语句一开始没有写,导致下面的select语句,无法解析导致报错了。

<!--  ****** 自定义的 带部门信息 的两种查询  ******  -->
<sql id="WithDept_Column_List">
  e.emp_id, e.emp_name, e.gender, e.email, e.d_id,d.dept_id,d.dept_name
</sql>

  <select id="selectByPrimaryKeyWithDept" resultMap="WithDeptResultMap">
   	select 
    <include refid="WithDept_Column_List" />
    FROM tbl_emp e
	left join tbl_dept d on e.`d_id`=d.`dept_id`
    where emp_id = #{empId,jdbcType=INTEGER}
  </select>

 

java踩坑-web后端获取路径的方法差异及注意点

方法一:

String path = Test.class.getResource("/").toString(); 
System.out.println("path = " + path);

此方法在tomcat下面没有问题,可以取到WEB-INF/classes
path = file:/home/ngidm_db2/AS_Tomcat7_0_29/webapps/NGIDM/WEB-INF/classes/
但换weblogic之后,取到的为
path = file:/oracle/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/
在weblogic下面,没能拿到classes路径。

方法二:

String path2 = Thread.currentThread().getContextClassLoader().getResource("/").getPath();
System.out.println("path2 = " + path2);

在tomcat和weblogic下面均可取到classes路径
path2 = /oracle/weblogic/Oracle/Middleware/user_apps/NGIDM/WEB-INF/classes/
path2 = /home/ngidm_db2/AS_Tomcat7_0_29/webapps/NGIDM/WEB-INF/classes/
故建议大家多使用
Thread.currentThread().getContextClassLoader().getResource("/").getPath();
获取classpath路径,且方法2 取到的classpath不含file:前缀,可以直接使用。
但是方法二,在JDK 7 和JDK8中会报错 返回 null ,所以要稍微改一下:
要么改成:Thread.currentThread().getContextClassLoader().getResource(".").getPath()
要么改成:Thread.currentThread().getContextClassLoader().getResource("").getPath()

eclipse的maven项目补充:

当我用 eclipse 构建 Maven 的Web项目时,然后用Junit 单元测试,调用如下方法获取路径

Thread.currentThread().getContextClassLoader().getResource("").getPath()

获取到的路径是 :xxx/target/test-classes/    而期望的是     xxx/target/classes/  所以有问题。

因为test-classes文件夹内没有存放任何 class 文件,所有class 文件和配置文件都存放在classes文件夹内。所以正在执行的测试类,应该是在 classes 文件夹中。

原因是maven项目的目录问题:src/main/java/目录下的代码会存放到target/classes 文件夹下,src/test/java/目录下的代码会存放到target/test-classes文件夹下。同理:src/main/resources 目录下的文件也会存放到 target/classes 文件夹下。

@Test
	public void testCRUD() throws IOException{
	
        //下面这句话,加载的配置文件路径是   xxx/target/test-classes/log4j.xml  结果 找不到, 因为真正的路径是  xxx/target/classes/log4j.xml  
        //PropertyConfigurator.configure(Thread.currentThread().getContextClassLoader().getResource("").getPath()+"log4j.xml");  
        //因为无法正确加载路径,所以采取了 另一种 路径方法
        String config=System.getProperty("user.dir");//获取程序的当前路径 
        System.out.println("config="+config);
	PropertyConfigurator.configure(config+"/target/classes/log4j.xml");  

 
//     Log4j的 调用方法,版本是 1.X 的,  因为 log4j 2.x 的版本 ,配置文件和调用方法 都变不同了。 
//	Logger logger = Logger.getLogger(MapperTest.class); 
//      // 记录debug级别的信息  
//      logger.error("This is debug message."); 
		
	//1、创建SpringIOC容器  ,这个地方 却可以 正确加载 路径 xxx/target/classes/springIOC.xml
	ApplicationContext ioc = new ClassPathXmlApplicationContext("springIOC.xml");
	//2、从容器中获取mapper
	EmployeeMapper bean = ioc.getBean(EmployeeMapper.class);
		
	System.out.println(bean.selectByPrimaryKey(1));

}

 

 

参考自:https://blog.csdn.net/magi1201/article/details/18731581