jsp详细总结一(指令,Cookie,Session,response,分页,上传,下载)

一.开发项目前的配置

1.使用Eclipse开发Web项目(JSP项目) tomcat

2.在Eclipse中创建的Web项目:

浏览器可以直接访问 WebContent中的文件,
例如http://localhost:8888/MyJspProject/index1.jsp
其中的index1.jsp就在WebContent目录中; 但是WEB-INF中的文件
无法通过客户端(浏览器)直接访问,只能通过请求转发来访问
注意:并不是 任何的内部跳转都能访问WEB-INF;原因是 跳转有2种方式:请求转发 、重定向

3.配置tomcat运行时环境

jsp<->Servlet
a.将tomcat/lib中的servlet-api.jar加入项目的构建路径
b.右键项目->Build Path -> Add library ->Server Runtime
4.部署tomcat

在servers面板 新建一个 tomcat实例 , 再在该实例中 部署项目(右键-add)之后运行
注意:一般建议 将eclipse中的tomcat与 本地tomcat的配置信息保持一致: 将eclipse中的tomcat设置为托管模式:【第一次】创建tomcat实例之后, 双击,选择Server Location的第二项

5.统一字符集编码

a.编码分类:
设置jsp文件的编码(jsp文件中的pageEncoding属性): jsp -> java
设置浏览器读取jsp文件的编码(jsp文件中content属性)
一般将上述设置成 一致的编码,推荐使用UTF-8
文本编码:
i.将整个eclipse中的文件 统一设置 (推荐)
ii.设置 某一个项目
iii.设置单独文件

二.jsp基础知识

JSP的页面元素: HTML java代码(脚本Scriptlet)、指令、注释
1.脚本Scriptlet

i.    
	<%
			局部变量、java语句
	%>
ii.
	<%!
			全局变量、定义方法
	%>
iii.
	 <%=输出表达式 %>

一般而言,修改web.xml、配置文件、java 需要重启tomcat服务
但是如果修改 Jsp\html\css\js ,不需要重启
2.指令
page指令

<%@ page …%>
page指定的属性:

language:jsp页面使用的脚本语言
import:导入类

pageEncoding:jsp文件自身编码 jsp ->java
contentType:浏览器解析jsp的编码

<%@ page language=“java” contentType=“text/html; charset=UTF-8”
pageEncoding=“UTF-8” import=“java.util.Date” %>
3.注释

html注释 ,可以被客户 通过浏览器查看源码 所观察到
java注释// /…/
jsp注释<%-- --%>
4.JSP九大内置对象(自带的,不需要new也能使用对象)

out:输出对象,向客户端输出内容
request:请求对象;存储“客户端向服务端发送的请求信息”
request对象的常见方法:
String getParameter(String name) :根据请求的字段名key (input标签的name属性值) ,返回字段值value (input标签的value属性值)
String[] getParameterValues(String name): 根据请求的字段名key ,返回多个字段值value (checkbox)
void setCharacterEncoding(“编码格式utf-8”) :设置post方式的请求编码 (tomcat7以前默认iso-8859-1,tomcat8以后改为了utf-8)
getRequestDispatcher(“b.jsp”).forward(request,response) ; :请求转发 的方式跳转页面 A - > B
ServletContext getServerContext():获取项目的ServletContext对象
4.统一请求的编码 request
1.get方式请求 如果出现乱码,解决:(请求乱码)

a.统一每一个变量的 编码 (不推荐)
new String( 旧编码,新编码);
name = new String(name.getBytes(“iso-8859-1”),“utf-8”);

修改server.xml ,一次性的 更改tomcat默认get提交方式的编码 (utf-8)
建议 使用tomcat时, 首先在server.xml中 统一get方式的编码… URIEncoding=“UTF-8”

tomcat7 (iso-8859-1)
tomcat8(utf-8)

2.post 方式请求 如果出现乱码,解决:

request.setCharacterEncoding(“utf-8”) ;

5.response :响应对象
提供的方法:

void addCookie( Cookie cookie ); 服务端向客户端增加cookie对象
void sendRedirect(String location ) throws IOException; :页面跳转的一种方式(重定向)
void setContetType(String type):设置服务端响应的编码(设置服务端的contentType类型)
中文乱码(响应乱码)
response.setContentType(“text/html”; charset=“UTF-8”);
response.setCharacterEncoding(“utf-8”);

转发、重定向:

转发:

张三(客户端) -> 【 服务窗口 A (服务端 ) -> 服务窗口B 】
重定向:

张三(客户端) -> 服务窗口 A (服务端 ) ->去找B
张三(客户端) -> 服务窗口 B (服务端 ) ->结束
6. session(服务端)
Cookie(客户端,不是内置对象):Cookie是由 服务端生成的 ,再发送给客户端保存。
相当于 本地缓存的作用: 客户端(hello.mp4,zs/abc)->服务端(hello.mp4;zs/abc)
作用:提高访问服务端的效率,但是安全性较差。

Cookie: name=value
javax.servlet.http.Cookie

public Cookie(String name,String value) //构造方法
String getName(): //获取name
String getValue(): //获取value
void setMaxAge(int expiry); //最大有效期 (秒)
服务端准备Cookie:

response.addCookie(Cookie cookie)
客户端获取cookie: request.getCookies();
a.服务端增加cookie :response对象;客户端获取对象:request对象
b.不能直接获取某一个单独对象,只能一次性将 全部的cookie拿到

通过F12可以发现 除了自己设置的Cookie对象外,还有一个name为 JSESSIONID的cookie

建议 cookie只保存 英文数字,否则需要进行编码、解码

7.session会话:

客户端第一次请求服务端时,(jsessionid-sessionid)服务端会产生一个session对象(用于保存该客户的信息);

并且每个session对象 都会有一个唯一的 sessionId( 用于区分其他session);

服务端由会 产生一个cookie,并且 该cookie的name=JSESSIONID ,value=服务端sessionId的值;

然后 服务端会在 响应客户端的同时 将该cookie发送给客户端,至此 客户端就有了 一个cookie(JSESSIONID);

因此,客户端的cookie就可以和服务端的session一一对应(JSESSIONID - sessionID)

客户端第二/n次请求服务端时:服务端会先用客户端cookie种的JSESSIONID 去服务端的session中匹配sessionid,如果匹配成功(cookie jsessionid和sesion sessionid),说明此用户 不是第一次访问,无需登录;

1.session方法:

String getId() :获取sessionId
boolean isNew() :判断是否是 新用户(第一次访问)
void invalidate():使session失效 (退出登录、注销)
void setAttribute()
Object getAttribute();
void setMaxInactiveInterval(秒) :设置最大有效 非活动时间
int getMaxInactiveInterval():获取最大有效 非活动时间
cookie和session的区别:
在这里插入图片描述

三.分页SQL

假设每页显示10条数据

1.mysql分页:
mysql:从0开始计数

结论:
分页:
第n页的数据: 第(n-1)10+1条 – 第n10条
mysql的分页语句:
limit 开始,多少条

select * from student limit 页数*页面大小,页面大小

2.sqlserver/oracle:从1开始计数
第n页 开始 结束
1 1 10
2 11 20
3 21 30
n (n-1)10+1 n10

select *from student where sno >=(n-1)10+1 and sno <=n10 ; --此种写法的前提:必须是Id连续 ,否则 无法满足每页显示10条数据

–1.如果根据sno排序则rownum会混乱(解决方案:分开使用->先只排序,再只查询rownum) 2.rownum不能查询>的数据

select s.* from student s order by sno asc;

select rownum, t.* from
(select s.* from student s order by sno asc) t
where rownum >=(n-1)10+1 and rownum <=n10 ;
3.oracle的分页查询语句:

select *from 
(
	select rownum r, t.* from
	(select s.* from student s order by sno asc) t 		
)
where r>=(n-1)*10+1 and <=n*10  ;	

优化:

select *from 
(
	select rownum r, t.* from
	(select s.* from student s order by sno asc) t 		
	where rownum<=n*10 
)
where r>=(n-1)*10+1  ;	

select *from 
(
	select rownum r, t.* from
	(select s.* from student s order by sno asc) t 		
	where  rownum<=页数*页面大小 
)
where r>=(页数-1)*页面大小+1  ;	

4.QLServer分页: 3种分页sql
row_number() over(字段) ;

sqlserver2003:top --此种分页SQL存在弊端(如果id值不连续,则不能保证每页数据量相等)

select top 页面大小 * from student where id not in 
( select top (页数-1)*页面大小 id from student  order by sno asc )

2.sqlserver2005之后支持:

select *from 
(
	select row_number()  over (sno order by sno asc) as r,* from student
			
	 where r<=n*10 
)
where r>=(n-1)*10+1 ;	

SQLServer此种分页sql与oralce分页sql的区别: 1.rownum ,row_number() 2.oracle需要排序(为了排序,单独写了一个子查询),但是在sqlserver 中可以省略该排序的子查询 因为sqlserver中可以通过over直接排序

3.sqlserver2012之后支持:
offset fetch next only

select * from student order by sno 
offset (页数-1)*页面大小+1  rows fetch next 页面大小  rows only ;

4.分页实现

5个变量(属性)
1.数据总数 100 103 (查数据库,select count(*)…)
2.页面大小 (每页显示的数据条数)20 (用户自定义)
3.总页数 (程序自动计算)
总页数 = 100/20 =数据总数/页面大小
总页数 = 103/20 = 数据总数/页面大小+1
—>

总页数 = 数据总数%页面大小==0? 数据总数/页面大小:数据总数/页面大小+1 ;

4.当前页(页码) (用户自定义)
5.当前页的对象集合(实体类集合):每页所显示的所有数据 (10个人信息)
List (查数据库,分页sql)

代码详细

//Dao数据操作层
	public List<Student> queryStudentsByPage(int currentPage, int pageSize) {
		String sql = "select *from "
					+"("
				    +"select rownum r, t.* from"
					+"(select s.* from student s order by sno asc) t "
				    
					+"where rownum<=?"
					+")"
					+ "where r>=?"
				 ;
		Object[] params = {currentPage*pageSize,(currentPage-1)*pageSize+1}; 
		
		List<Student> students = new ArrayList<>();
		
		ResultSet rs = DBUtil.executeQuery(sql, params) ;
		
		try {
			while(rs.next()) {
				Student student = new Student(rs.getInt("sno"),rs.getString("sname"),rs.getInt("sage"),rs.getString("saddress")) ;
				students.add(student) ;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}catch (Exception e) {
			e.printStackTrace();
		}
		return students;
	}


//Servlet显示层后台
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		IStudentService studentService  = new StudentServiceImpl();
		int count = studentService.getTotalCount() ;//数据总数
		
		//将分页所需的5个字段(其中有1个自动计算,因此实际只需要组装4个即可),组装到page对象之中
		Page page = new Page();
			
		String cPage = request.getParameter("currentPage")  ;//
				
		if(cPage == null) {
			cPage = "1" ;
		}
				
		int currentPage = Integer.parseInt( cPage );
		page.setCurrentPage(currentPage);
//		int currentPage = 2;//页码
		
		//注意 顺序
		int totalCount = studentService.getTotalCount() ;//总数据数
		page.setTotalCount(totalCount);
		
		/* currentPage:当前页(页码)  
	  	 students :当前页的数据集合(当前页的所有学生)
		
		*/
		int pageSize = 3;
		page.setPageSize(pageSize);
		List<Student>  students  = studentService.queryStudentsByPage(currentPage, pageSize) ;
		System.out.println(students);
		System.out.println(count);
		
		
		page.setStudents(students);
		request.setAttribute("p", page);
		request.getRequestDispatcher("index.jsp").forward(request, response);
		
	}


//jsp页面
<table border="1px">
			<tr>
				<th>学号</th>
				<th>姓名</th>
				<th>年龄</th>
				<th>操作</th>
			</tr>		
			<%
				//获取request域中的数据
				Page p  = (Page)request.getAttribute("p") ;									
				for(Student student:p.getStudents()){
			%>
					<tr>
						<td><a href="QueryStudentBySnoServlet?sno=<%=student.getSno() %>"><%=student.getSno() %></a>      </td>											
						<td><%=student.getSname() %></td>
						<td><%=student.getSage() %></td>
						<td> <a href="DeleteStudentServlet?sno=<%=student.getSno() %>   ">删除</a> </td>				
					</tr>
			<%
				}	
			%>	
		</table>
		<a href="add.jsp">新增</a><br/>
		
		<%
				if(p.getCurrentPage() ==p.getTotalPage()){ //尾页
		%>			<a href="QueryStudentByPage?currentPage=1">首页</a>
					<a href="QueryStudentByPage?currentPage=<%=p.getCurrentPage()-1%>    ">上一页</a>
		<% 
				}	
				else if(p.getCurrentPage() ==1){//首页
		%>		<a href="QueryStudentByPage?currentPage=<%=p.getCurrentPage()+1%> ">下一页</a>
				<a href="QueryStudentByPage?currentPage=<%=p.getTotalPage()%>">尾页</a>
		<%		
			}
				else{//中间
			%>		
					<a href="QueryStudentByPage?currentPage=1">首页</a>
					<a href="QueryStudentByPage?currentPage=<%=p.getCurrentPage()-1%>    ">上一页</a>
					<a href="QueryStudentByPage?currentPage=<%=p.getCurrentPage()+1%> ">下一页</a>
					<a href="QueryStudentByPage?currentPage=<%=p.getTotalPage()%>">尾页</a>	
			<%			
				}

5.上传和下载
1.引入2个jar

apache: commons-fileupload.jar组件
commons-fileupload.jar依赖 commons-io.jar

2.代码:
前台jsp:

表单提交方式必须为post
在表单中必须增加一个属性 entype=“multipart/form-data”

3.下载:不需要依赖任何jar
a.请求(地址a form),请求Servlet
b.Servlet通过文件的地址 将文件转为输入流 读到Servlet中
c.通过输出流 将 刚才已经转为输入流的文件 输出给用户
注意:下载文件 需要设置2个 响应头:
response.addHeader(“content-Type”,“application/octet-stream” );//MIME类型:二进制文件(任意文件)
response.addHeader(“content-Disposition”,“attachement;filename=”+fileName );//fileName包含了文件后缀:

实现代码:

//前端页面

<form action="UploadServet" method="post"  enctype="multipart/form-data">
			学号:<input name="sno" /><br/>
			姓名:<input name="sname" /><br/>
			上传照片: <input type="file"  name="spicture"/>
			<br/>
			<input type="submit" value="注册"/>
		</form>
		<a href="DownloadServlet?filename=MIME.png">MIME</a>

后台代码

//Servlet上传照片代码
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=UTF-8");
		// 上传
		// request.getParameter("sname")
		try {
			boolean isMultipart = ServletFileUpload.isMultipartContent(request);
			if (isMultipart) {// 判断前台的form是否有 mutipart属性
//				FileItemFactory factory = new DiskFileItemFactory();
				DiskFileItemFactory factory = new DiskFileItemFactory();
				
				ServletFileUpload upload = new ServletFileUpload(factory);
				
				//设置上传文件时 用到的临时文件的大小DiskFileItemFactory
				factory.setSizeThreshold(10240);//设置临时的缓冲文件大小为10
				factory.setRepository(new File("D:\\study\\uploadtemp"));//设置临时文件的目录
				//控制上传单个文件的大小  20KB ServletFileUpload
				upload.setSizeMax(20480);//字节B
				Thread.sleep(3000);
															
				// 通过parseRequest解析form中的所有请求字段,并保存到 items集合中(即前台传递的sno sname
				// spicture此时就保存在了items中)
				List<FileItem> items = upload.parseRequest(request);
				// 遍历items中的数据(item=sno sname spicture)
				Iterator<FileItem> iter = items.iterator();
				while (iter.hasNext()) {
					FileItem item = iter.next();
					String itemName = item.getFieldName();
					int sno = -1;
					String sname = null;
					// 判断前台字段 是普通form表单字段(sno sname),还是文件字段

					// request.getParameter() -- iter.getString()
					// 判断是否是普通表单字段
					if (item.isFormField()) {
						if (itemName.equals("sno")) {// 根据name属性 判断item是sno sname 还是spicture?
							sno = Integer.parseInt(item.getString("UTF-8"));
						} else if (itemName.equals("sname")) {
							sname = item.getString("UTF-8");
						} else {
							System.out.println("其他字段xxx.....");
						}
					} else {// spicture 123
							// 文件 上传
							// 文件名 getFieldName是获取 普通表单字段的Name值
							// getName()是获取 文件名
						String fileName = item.getName();//a.txt   a.docx   a.png
						String ext = fileName.substring(  fileName.indexOf(".")+1 ) ;
						if(!(ext.equals("png") || ext.equals("gif") ||ext.equals("jpg"))) {
							System.out.println("图片类型有误!格式只能是 png gif  jpg");
							return ;//终止
						}
						// 获取文件内容 并上传
						// 定义文件路径:指定上传的位置(服务器路径)
						// 获取服务器路径D:\\study\\apache-tomcat-8.5.30\\wtpwebapps\\UpAndDown\\upload
						// String path =request.getSession().getServletContext().getRealPath("upload") ;
						String path = "D:\\study\\upload";

						File file = new File(path, fileName);
											
						item.write(file);// 上传
						System.out.println(fileName + "上传成功!");
						return;
					}
				}
			}
		}
		catch (FileUploadBase.SizeLimitExceededException e) {//SizeLimitExceededException是FileUploadException的一个子类
			System.out.println("上传文件大小超过限制!最大20KB");
		}
		catch (FileUploadException e) 
		{
			e.printStackTrace();		
		}		
		// 解析请求
		catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}



//Servlet 下载代码
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		//获取需要下载的文件名
		String fileName = request.getParameter("filename") ;//form  、a  href、 ...Server?a=b
		
		//下载文件:需要设置 消息头
		response.addHeader("content-Type","application/octet-stream" );//MIME类型:二进制文件(任意文件)
		response.addHeader("content-Disposition","attachement;filename="+fileName );//fileName包含了文件后缀:abc.txt
		
		//Servlet通过文件的地址  将文件转为输入流 读到Servlet中
		InputStream in = getServletContext().getResourceAsStream("/res/MIME.png") ;
		
		//通过输出流 将 刚才已经转为输入流的文件  输出给用户
		ServletOutputStream out = response.getOutputStream() ;
		byte[] bs = new byte[10];
		int len=-1 ;
		while(  (len=in.read(bs)) != -1) {
			out.write(bs,0,len);
		}
		out.close();
		in.close();
		
	}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
采用Eclipse 编写的关于省市县三级菜单采用JSP +servlet+MYSQL ,数据库表的数据文件在src文件夹中 mysql> show tables; +----------------+ | Tables_in_area | +----------------+ | area | | cities | | provinces | +----------------+ 3 rows in set (0.00 sec) mysql> desc provinces; +----------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | pid | char(6) | NO | | NULL | | | province | varchar(100) | NO | | | | +----------+--------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec) mysql> desc cities; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | cid | char(6) | NO | | NULL | | | city | varchar(40) | NO | | NULL | | | pid | char(6) | NO | | NULL | | +-------+-------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec) mysql> desc area; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | aid | char(6) | NO | | NULL | | | area | varchar(40) | NO | | NULL | | | cid | char(6) | NO | | NULL | | +-------+-------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值