Java学习之路-Servlet/JSP

531 阅读19分钟
一、web应用程序

静态web应用程序:特点页面的内容不会实时更新(由html标签码出来的,需要手动更新,所以维护比较麻烦,优点是响应快,纯静态的web应用基本不能满足企业的业务需要) ---html,css,js

动态web应用程序:页面的内容是通过程序生成的(请求某一页面,实时生成--不请求,页面内容一般不存在)

主流的动态 web应用开发技术:

JSP : Java server page

PHP:Hypertext Preprocessor --- 做网站

ASP: Active Server Page --- (ASP.NET) --- .NET Core --- Linux

如果WEB应用程序框架采用 前后端分离技术实现

HTTP协议 :协议头信息 + 正文

请求头
request URL: http://commons.apache.org/proper/commons-email/index.html
Request Method: GET
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Cookie: _ga=GA1.2.1144907725.1591022909
Host: commons.apache.org
Pragma: no-cache
Referer: http://commons.apache.org/proper/commons-email/building.html
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36
 

响应头
Status Code: 200 OK
Remote Address: 40.79.78.1:80
Referrer Policy: no-referrer-when-downgrade
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 3253
Content-Type: text/html
Date: Sat, 27 Jun 2020 02:31:23 GMT
ETag: "43ec-5661b25fe503d-gzip"
Keep-Alive: timeout=5, max=2000
Last-Modified: Mon, 26 Feb 2018 10:41:11 GMT
Server: Apache/2.4.18 (Ubuntu)
Vary: Accept-Encoding
 

二、web服务器

服务器:支持解析动态资源(程序|数据库访问|其它web资源|....)

Tomcat :sun开发源出来的,免费web服务器 (由apache,sun,其它公司及个人共同维护 ),开发语言JAVA,Tomcat适合中小项目

Tomcat:https://tomcat.apache.org/
64-bit Windows zip (pgp, sha512) :64位免安装版

WebSphere :IBM开发的Web服务器 --- 收费的

WebLogic :Oracle开发的web服务器 -- 收费的

JBoss :由jBoss公司开发web 服务器 (开源的)

.......

三、tomcat服务器安装与测试

推荐:解压放到一个非中文目录下

启动tomcat
启动脚本:/bin/startup.bat (注:不要频繁启动多次,否则会出错)

请求:http://192.168.1.123:8080/  | http:localhost:8080/ | http://127.0.0.1:8080/
关闭tomcat
/bin/shutdown.bat
tom目录结构
--------------------------------------------------------------------
bin :放启动/关闭tomcat服务器相关脚本命令
conf:tomcat配制信息(xml) www默认端口为80端口(如果是80端口,在请求服务器资源时,可以省)
lib:tomcat软件依赖的jar包
logs:日志文件存放位置
temp:存放tomcat运行时产生的临时数据
webapps:项目默认发布位置
work目录:所有的jsp资源编译存放的位置
四、开发一个JAVAEE的工程

在Eclispe中配制tomcat

window --preferences--- server 

创建一个JAVAEE项目(略 )

发布项目到tomcat :默认发布的位置并没有放在:webapps目录下,需要设置

JAVAEE项目目录结构
web-hello(项目名)
  --META-INF (放元数据)
  --WEB-INF (放项目资源,整个WEB应程序所有的服务器资源基本放在此目录)
   --lib 项目运行依赖的jar包(放到此目录下,会自动加载到build path路径下)
   --web.xml
  --index.jsp(首页)
五、理解JSP页面

通过查看tomcat,得到到:index.jsp ----- 服务器会将所有的jsp页面解析成一个java类(由tomcat完成),存放在work目录下; 当请求某一个jsp文件时,web服务直接运行*.class文件,得到纯静态的html数据,发送给浏览器

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
public abstract class HttpJspBase extends HttpServlet
public abstract class HttpServlet extends GenericServlet
public abstract class GenericServlet implements Servlet, ServletConfig
public interface Servlet 
结论:所有的JSP本质是一个实现Servlet接口的一个对象
六、Servlet入门
1、理解Servlet
A servlet is a small Java program that runs within a Web server. Servlets receive and respond to requests from Web clients, usually across HTTP, the HyperText Transfer Protocol.
2、创建Servlet
  • 通过实现Servlet接口创建一个Servlet(1个运行中web server上的小程序)
  • 继承GenericServlet 创建一个Servlet
  • 继承HttpServlet创建一个 Servlet

第一步:写一个类,实现Servlet接口

public class Servlet1 implements Servlet {
	//....
	@Override
	public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
		System.out.println("一个用户请求了本Servlet对象");
	}
}

第二步:在web.xml中配制Servlet

项目中所有Servlet的创建由tomcat服务器完成,所以,需要在项目配制哪些Servlet需要创建对象;

 <servlet>
  	 <servlet-name>Servlet01</servlet-name>
  	 <servlet-class>cn.lanqiao.servlet.Servlet1</servlet-class>
  	  <load-on-startup>1</load-on-startup>
  	  <!-- 
  	  	load-on-startup :在web服务器启动时就创建本servlet对象,并初使化
  	  	参数值决定创建的顺序
      -->
  </servlet>
  <servlet-mapping>
  	 <servlet-name>Servlet01</servlet-name>
  	 <url-pattern>servlet01.do</url-pattern>
  </servlet-mapping>

对web.xml的修改必须重新服务器

第三步:测试

http://192.168.1.123:8080/servletproject/servlet01.do

/user/list
/user/add.html | /user/add.do | /user/add.action
*.lanqiao | *.do
/user/*

3、Servlet的生命周期
  • 创建并初使化一个Servlet (单例的)
  • 调用service方法接收和响应来自用户的请求
  • 当关闭web服务时,servlet将从容器中销毁
4、继承GenericServlet创建Servlet
public class Servlet3 extends GenericServlet {
	private static final long serialVersionUID = 1L;
	@Override
	public void service(ServletRequest req, ServletResponse response) throws ServletException, IOException {
		response.getWriter().write("this is servlet3");
	}
}

相对基于接口实现,此方式要简洁一些;(缺点:需要手动区分用户请求的方式 :GET|POST|PUT......)

5、继承HttpServlet创建Servlet
public class Servlet4 extends HttpServlet {
	private static final long serialVersionUID = 1L;
	//对web访问来说,主要的请求方式:GET | POST(表单提单)
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.getWriter().write("this is servlet4");
	}
}

小结:通过HttpServlet创建 的Servlet最方便(开发中,主要使用此方式)

6、Servlet3.0(基于注解发布)

@WebServlet

String name() :<servlet-name></servlet-name>
String[] value() : <url-pattern></url-pattern>
int loadOnStartup()  :<load-on-startup></load-on-startup>
WebInitParam[] initParams():<init-param></init-param>

七、Servlet进阶

Servlet有9大内置对象(由web服务器提供,直接拿来用),每一个内置对象都有特定的应用;

1、ServletConfig

作用:获取本Servlet的初使化参数信息 (了解)

<servlet>
 	<servlet-name>Servlet4</servlet-name>
 	<servlet-class>cn.lanqiao.servlet.Servlet4</servlet-class>
 	<init-param>
 		<param-name>encode</param-name>
 		<param-value>UTF-8</param-value>
 	</init-param>
 </servlet>

得到ServletConfig对象

ServletConfig config= this.getServletConfig();

获取initparam

String encode= config.getInitParameter("encode"); //单个参数;

Enumeration<String> names = config.getInitParameterNames(); //获取所有参数名 ;
while(names.hasMoreElements()) {
String name = names.nextElement();
System.out.println(name +" -> " + config.getInitParameter(name));
}

2、ServletContext

如何每一个Servlet都可以获取共同参数信息?此参数信息不能定义在某一个Servlet内部,必须做全局的(所有Servlet共享的|共有的);

在web.xml中定义全局的参数,每一个Servlet都可以访问此参数,但不能通过ServletConfig对象去拿
<context-param>
    <param-name>encode</param-name>
    <param-value>UTF-8</param-value>
</context-param>

ServletContext :带表一个web应用程序,在web服务器启动时,会创建此对象(只有一个),此对象只在服务器关闭时,才销毁;此对象是可以存数据(所有的Servlet共享的),但一般不会在此对象中存,原因对象一直活着,对象存的数据就存在,如果不断向此对象存数据,内存会慢慢消耗掉

得到ServletContext对象

ServletContext context=this.getServletContext();

获取参数

//		String encode= context.getInitParameter("encode");
//		String userString=context.getInitParameter("user");
//		String passwordString=context.getInitParameter("password");
//		System.out.println(encode);
//		System.out.println(userString);
//		System.out.println(passwordString);
Enumeration<String> names= context.getInitParameterNames();
while(names.hasMoreElements()) {
    String nameString=names.nextElement();
    System.out.println(nameString +" -> " + context.getInitParameter(nameString));
}

存共享数据

在ServletA中,向ServletContext对象存了两个值;
context.setAttribute("uname", "张一");
context.setAttribute("sex", "男");

拿ServletContext对象的数据

在ServletB中,从ServletContext对象中取数据
System.out.println(context.getAttribute("uname"));
System.out.println(context.getAttribute("sex"));

结论:不管在哪一个Servlet中,得到的ServletContext对象为同一个对象 一个工程只有一个ServletContext对象

通过ServletContext对象获工程中资源【重点】

获取src下资源|获取类路径下的资源

String path= "WEB-INF/classes/db.properties"; //相对发布的项目根位置 ;
//对文件的操作IO -- 需要绝对路径;
String  absolutePath= context.getRealPath(path);
java.util.Properties properties=new Properties();
InputStream inStream = new FileInputStream(absolutePath);
properties.load(inStream);
String driver = properties.getProperty("driver");
String user = properties.getProperty("user");
System.out.println(driver );
System.out.println(user);
inStream.close();
--------------------------------------------------------------------------
InputStream inputStream =context.getResourceAsStream(path);
java.util.Properties properties=new Properties();
properties.load(inputStream);
System.out.println(properties.getProperty("password"));

获取包下的资源?

获取项目根目录下的资源

String path3 = context.getRealPath("/1.txt");
InputStream inputStream2=context.getResourceAsStream(path3);

3、commons-io组件

Commons IO :就appache下的一个开源项目,commons io功能对JAVA IO原生 API 进行封装,对文件与目录操作提供简单易用的API,最新版(2.7),组件下的几个常用工具类:CopyUtils|FileUtils|FilenameUtils|IOUtils

下载:https://commons.apache.org/proper/commons-io/

ServletContext context=this.getServletContext();
//String contString = IOUtils.toString(context.getResourceAsStream("/WEB-INF/classes/1.txt"),"UTF-8");
//String contString=IOUtils.toString(new URL(context.getRealPath("/WEB-INF/classes/1.txt")),"UTF-8");
List<String> list = IOUtils.readLines(context.getResourceAsStream("/WEB-INF/classes/1.txt"),"UTF-8");
System.out.println(list);

4、HttpServletResponse

每一次http请求web服务器资源(servlet),在web服务器中,都会创建Servlet几个内置对象,HttpServletResponse对象用来向用户输出信息的,HttpServletRequest对象,获取用户发送过来的信息

设置输出信息的字符编码

//控制输出信息的字符编码;
response.setCharacterEncoding("UTF-8"); //设置输出的字符编码为UTF-8;
//需要控制浏览器以UTF-8编码解析(打开)
response.setHeader("Content-Type","text/html; charset=UTF-8");

向用户输出信息

需要得到PrintWriter (直接输出字符数据)或者ServletOutputStream对象(以流格式输出)

PrintWriter printWriter = response.getWriter();
printWriter.write("hllo");
printWriter.print("Hello"); //print方法的重载的版本数量比write多一些,其它没区别;

ServletOutputStream outputStream =response.getOutputStream();
//向浏览器输出一张图片;
ServletContext context= this.getServletContext();
InputStream inputStream = context.getResourceAsStream("/images/books.jpg");
byte[] datas = new byte[inputStream.available()];
IOUtils.read(inputStream,datas);
outputStream.write(datas);

页面重定向

页面跳转:从一个页面转到另一个页面 | 从一个Servlet转到另一个Servlet | servlet转到某一个页面

response.sendRedirect("servlet1");
response.sendRedirect("/web-servlet/servlet1");
response.sendRedirect("/web-servlet/index.jsp");
response.sendRedirect("http://localhost:8080/web-servlet/servlet1");

页面刷新

<meta http-equiv="refresh" content="1" />
response.setHeader("refresh", "1"); //每隔1秒刷新一次;

文件下载

String path="/down/6.Servlet入门-1.wmv";
ServletContext context=this.getServletContext();
InputStream inputStream=context.getResourceAsStream(path);
String filename=FilenameUtils.getName(path);
//处理中文名称;
String newFilename = URLEncoder.encode(filename,"UTF-8");

//控制浏览器以下载的方式写入此资源
response.setHeader("Content-Disposition", "attachement;filename=" + newFilename);
ServletOutputStream outputStream = response.getOutputStream();
IOUtils.copy(inputStream, outputStream);
outputStream.close();
inputStream.close();

5、PrintWriter

ServletOutputStream

6、HttpServletRequest

HttpServletRequest对象(request对象):接收用户提交的数据(通过表单方式提交,通过url后参数提交)

接收用户提交的数据

String uname = request.getParameter("uname");
如果文本框中有中文,需要做编码设置
request.setCharacterEncoding("UTF-8");

接收http协议信息

//获取 HTTP请求头信息
String accept = request.getHeader("Accept");

Enumeration<String> names = request.getHeaderNames();
while(names.hasMoreElements()) {
    String hname = names.nextElement();
    System.out.println(hname +" -> " + request.getHeader(hname));
}

获取URL信息

http://localhost:8080/web-servlet/servlet4?id=1&name=abc&type=1

System.out.println(request.getScheme());
System.out.println(request.getServerName());
System.out.println(request.getServerPort());
System.out.println(request.getContextPath());
System.out.println(request.getServletPath());
System.out.println(request.getQueryString());

Web资源访问【重点|难点】

web资源可以存放的位置:一个项目根目录下 | 一个为项目根目录的WEB-INF目录下 ;两者不一样的,对根目录下的资源,访问是不受限制的,而对于WEB-INF下资源,用户是不能直接访问的 ,所以,在正常开发中,项目资源基本上放在WEB-INF,如果需要返回WEB-INF下的资源,需要通过服务器内部转发才可以 --- request对象实现

Servlet有三大域对象(可以存数据的对域称为域对象) :ServletContext | HttpSession| HttpServletRequest

在:HttpServletRequest域对象中存数据,数据有效在整http请求链中都可以访问;

存数据
request.setAttriubte(key,value);
转发
request.getRequestDispatcher("/WEB-INF/main.jsp").forward(request, response);

login --->/web-servlet/login/ ---->main.jsp

重定向(response.sendRedirect(url)) 与转发的区别(request.getRequestDispatcher(url).forward(r,r))

区别:转发在整个处理中只发生一次请求,URL没有发生变化;

重定向:发生了2次请求(第1次:/web-servlet/login,第2次:/main.jsp ),2次响应,地址栏会发生变化(最后一次请求的地址会显示)

四层: 表示层(html | jsp) -- Servlet(控制层) --- 业务层 ---数据层

控制层命名:名的名称一般为:controller

控制层中的类命名(控制器):xxxController;

7、HttpSessoin

HttpSession对象表示会话,每访问一个页面,就标识与当前页面建立了一次会话,服务器会给本次会话分配一个会话的id(sesssionid),id全球唯一;sessionid会发送给用户(以临时cookie方式),同时在服务器在一份(???);session是一个servlet中的域对象,此对象中通常存用户的身份信息,session对象存放的数据可以跨页面访问(同一个窗口)

简单的权限验证:基于session实现;

获取session对象

HttpSession session = request.getSession();

session对象存取数据

session.setAttribute(key,value);
session.getAttribute(key)
session.removeAttribute(key)

session数据存活期

ServletContext存活期:服务器不关,就一直存在
session存活期:默认30分钟(可以改)
request荐活期:只要窗口不关,请求域就在存在,数据就存在
<session-config>
	<session-timeout>40</session-timeout>
</session-config>

8、this
9、Exception

在JSP页面用;必须:isErrorPage="true"

<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8" isErrorPage="true"%>

<%=exception.getMessage()%>

10、PageContext

放到jsp中学习

11、图片验证码

理解验证码:登录、注册、发信息时,需要输入,验证码是图片(图片写入的信息为字符信息)

登录:防暴力破解

注册 | 发贴 :防止灌水

用JAVA动态生成一张内存中图片,通过img标签展示:BufferedImage | Graphic2D |ImageIO

response.setContentType("image/jpeg"); //控制输出信息格式为jpg图片
		//1 创建一个内存中的图片对象
		BufferedImage bufferImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
		//2 得到一个画笔
		Graphics2D g = (Graphics2D) bufferImage.getGraphics();
		//3 使用画笔绘验证码字符,绘制干扰线,.......
		//设置画笔的颜色;
		g.setColor(Color.WHITE);
		//填充背景
		g.fillRect(0, 0, WIDTH,HEIGHT);
		//画一个边框;
		g.setColor(Color.GREEN);
		g.drawRect(0, 0, WIDTH-1, HEIGHT-1);
		//画验证码:字母|数字的组合,可以中文(放中文常用字)
		String codes="abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ0123456789";
		Random rand = new Random();
		int left=10;
		g.setColor(Color.RED);
		//画笔的大小及字体调整一下
		g.setFont(new Font("雅黑",Font.BOLD, 20));
		String validateCode="";
		for(int i=0 ;i<4;i++) {
			int index = rand.nextInt(codes.length());
			char c = codes.charAt(index);
			validateCode+=c;
			//旋转一个角度
			int degree = rand.nextInt() % 30; //30度以内的角度;
			g.rotate(degree * Math.PI / 180,left,22); 
			g.drawString(String.valueOf(c), left, 22);
			g.rotate(-degree * Math.PI / 180,left,22); 
			left+=25;
			//转回来
		}
		//在服务器中存一份;
		request.getSession().setAttribute("code", validateCode);
		
		//画干扰线;
		g.setColor(Color.BLACK);
		for(int i=0;i<5;i++) {
			g.drawLine(rand.nextInt(15), rand.nextInt(15), rand.nextInt(WIDTH), rand.nextInt(HEIGHT));
		}
		//4、输出图片;
		ImageIO.write(bufferImage, "JPEG", response.getOutputStream());

12、发邮件

发邮件:需要有一个邮件服务器(一般稍微大一点公司都有自己的邮件服务器),学习使用第三方邮件服务器(腾讯QQ邮件服务器),需要开通发邮件服务;

邮件有专用的通信协议

STMP:Simple Mail Transfer Protocol

POP3:Post Office Protocol - Version 3

JDK中有发邮件组件,用起来不太方便,本次用Apache邮件组件,封装简易的API,简单,易用

http://commons.apache.org/proper/commons-email/
-- commons-email-1.5 
-- activation-1.1.jar
-- javax.mail-1.5.6

SimpleEmail 
MultiPartEmail 
HtmlEmail 
EmailAttachment 

1步:开发QQ邮箱的邮件服务
发短信:配置邮件客户端  到号码:1069 0700 69
得到一个授权码:npdoybdtbmwzbecg
第2步:发邮件
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
//发送一封简单格式的邮件;
Email email = new SimpleEmail();
//设置发送邮件的服务器
email.setHostName("smtp.qq.com");
email.setSmtpPort(25);
//身份验证
email.setAuthentication("879897096", "npdoybdtbmwzbecg");
try {
    //邮件主题;
    email.setSubject("这是一封测试邮件");
    //设置发件人;
    email.setFrom("879897096@qq.com","老徐");
    //设置收件人;
    email.addTo("1939603602@qq.com"); 
    //如果需要发给其他人,可以选择抄送;
    email.addCc("1739954617@qq.com","1026265505@qq.com");
    //密送
    email.addBcc("2497662216@qq.com","995728922@qq.com");
    //设置正文;
    email.setMsg("This is a 测试 mail ... :-)");
    String status = email.send();
    response.getWriter().write("发送成功"); 			
} catch (EmailException e) {
    e.printStackTrace();
}

13、文件上传

第1步:加载JAR包

FileUpload 上传的组件依赖: Commons IO

commons-fileupload-1.4.jar
commons-io-2.6.jar

第2步:编写页面

<form method="POST" enctype="multipart/form-data" action="/web-servlet/up">
  File to upload: <input type="file" name="upfile"><br/>
  Notes about the file: <input type="text" name="note"><br/>
  <br/>
  <input type="submit" value="Press">
</form>

表单提交方法必须为:POST;

enctype属性,默认属性值:enctype="application/x-www-form-urlencoded",如果表单中有上传控制,值必须为:multipart/form-data

第3步:编写Servlet,实现上传

request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=utf-8");
		boolean isMultiPart = ServletFileUpload.isMultipartContent(request);
//		if(!isMultiPart) {
//			response.getWriter().write("<script>alert('表单设置满足要求:entype值重新设置');location='upfile.jsp';</script>");
//		}
		if(isMultiPart) {
			//上传时在磁盘生成监时数据,存放文件;
			DiskFileItemFactory factory = new DiskFileItemFactory();
			ServletContext context = this.getServletContext();
			File repository = (File) context.getAttribute("javax.servlet.context.tempdir");
			factory.setRepository(repository);
			
			ServletFileUpload upload = new ServletFileUpload(factory);
			//Parse  request
			try {
				List<FileItem>  lists =upload.parseRequest(request);
				Iterator<FileItem> it = lists.iterator();
				while(it.hasNext()) {
					FileItem item = it.next();
					if(item.isFormField()) {
						//对普通的文本框加,直接打印数据;
						String name = item.getFieldName();
						String val = item.getString("UTF-8");
						System.out.println(name +" -> " + val);
						
					}
					if(!item.isFormField()) {
						//对文件域对象,实现上传;
						String fieldName = item.getFieldName(); //upfile
					    String fileName = item.getName(); //上传文件名;
					    String contentType = item.getContentType(); //上传的文件类型;
					    boolean isInMemory = item.isInMemory(); //是写到内存吗?
					    long sizeInBytes = item.getSize(); //文件大小 
					   //控制上传文件的类型;
					   //控制上传文件的大小;
					    //上传一般是改文件名;
					    String ext = FilenameUtils.getExtension(fileName); //.rar
					    String newName =String.valueOf(new java.util.Date().getTime()) + "." + ext;
					    String path =context.getRealPath("/upfiles") +"/"  + newName;
					    //将数据写入到磁盘中
					    File file = new File(path);
					    item.write(file);
					}
				
				}
				
			} catch (FileUploadException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}

14、发送短信

15、支付(支付宝)| 易宝支付(1分)

八、DbUtil工具类

dbutils是apache基金会下的一个开源项目,此项目设计了数据库访问相关工具类,直接可以取数据库中的数据并映射成相关对象(单个对象或者集合对象)

commons.apache.org/proper/comm…

熟练使用dbutils设计的 JDBC 操作 API

核心包:org.apache.commons.dbutils
  --org.apache.commons.dbutils.QueryRunner
    --query(String sql, ResultSetHandler<T> rsh, Object... params)
    --update(String sql,Object... params) //增删改
    --DbUtils--org.apache.commons.dbutils.ResultSetHandler 
     --BeanHandler<T> :单个对象的映射处理器;
     --BeanListHandler<T> :T 表示List集合中的元素类型 
     --ScalarHandler :单个值(如果返回值为整型:BigDecimal(oracle),mysql(Long))
     --ArrayHandler:映射为数组
     --ArrayListHandler:映射为List集合,集合里的元素为数组
     --MapHandler:映射为Map集合;
     --MapListHandler:映射为List集合,集合中每个元素为一个Map对象

九、过滤器

Javaweb三大核心组件之一:过滤器组件主要起拦截(所有对服务器资源的访问都需要先通过过滤器,过滤器放行后,才可以继续访问请求的资源)

过滤最常应用:权限验证 | 字符编码

第1步:创建过滤器

public class CharsetFilter implements Filter {
	private FilterConfig config;
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("init 过滤器");
		this.config = filterConfig;
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		//做拦截处理业务
		String encode = config.getInitParameter("encode");
		request.setCharacterEncoding(encode);
		//response.setCharacterEncoding(encode);
		//放行
		chain.doFilter(request, response);
	}
	@Override
	public void destroy() {
		System.out.println("destroy");
	}
}

第2步:发布过滤器

 <filter>
  		<filter-name>CharsetFilter</filter-name>
  		<filter-class>cn.lanqiao.filter.CharsetFilter</filter-class>
  		<init-param>
  			<param-name>encode</param-name>
  			<param-value>UTF-8</param-value>
  		</init-param>
  </filter>
  过滤器拦截什么资源,取决于urlpatten的设置
  <filter-mapping>
  	<filter-name>CharsetFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping> -



@WebFilter(
initParams = {@WebInitParam(name = "encode",value="UTF-8")},
urlPatterns= {"/*"} )

十、监听器(Listener)

监听器由用户创建

监听对象:Servlet中的三大域对象 ServletContext,HttpSession,HttpServletRequest; 可以监听对象的创建及销毁;也可以监听域对象数据的变化

监听不同的域对象,需要实现不能的监听接口ServletContextListener,HttpSessionListener,HttpServletRequestListener

第1步:创建监听器

public class RequestListener implements ServletRequestListener {
    public RequestListener() {
    	System.out.println("RequestListener 诞生了");
    }
    public void requestDestroyed(ServletRequestEvent sre)  { 
    	System.out.println("request对象 销毁了.....");
    }
    public void requestInitialized(ServletRequestEvent sre)  { 
    	System.out.println("request 创建了");
    }
	
}

第2步:发布监听器

@WebListener --基于注解
基于配制文件发布监听器
 <listener>
 	<listener-class>cn.lanqiao.listener.RequestListener</listener-class>
 </listener>


十一、JSP工作原理

  • 当请求服务器中某一个JSP页面时,Web服务当将JSP解析成一个JAVA类(本质是一个实现Servlet接口类),再编译此类,得到一个字节码文件 ,调用本类对象的service方法接收和响应用户的请求;
  • 第2次,直接调用service方法接受和响应用户的请求

JSP的本质是Servlet,一般在展示数据时,使用jsp方便一些,如果处理程序代码,一般选择Servlet; JSP的出现就是为了方便展示页面数据(先有Servlet,再有JSP)

十二、JSP语法
语法说明
<% %>JSP脚本,在<%%>中间可编写JAVA代码,<%%>是可以拆分的
<%= %>JSP表达式 :当<%%>中只有一条输出语句,可以省去out.write,用 "=" 替换即可
<%! %>JSP声明,可以声明变量,方法等对象
<%-- --%>JSP注释 (是不会在页面中显示的),HTML标签注释会在页面显示
JSP指令标签
<%@ page %>所有JSP页面都有一个page指令
<%@ include file="" %>在当前页 面包含一个页面(静态包含)
<%@ taglib %>导入JSP标签库(讲JSTL再说)
JSP动作标签
include包含文件
useBean通过标签声明得到一个JavaBean对象
getProperty
setProperty
forward转发

在JSP中,可以有2种语法将一个页面加载到别一个页面,一个是指令标签,一个动作标签,指令标签的包含称静态包含,所有被包含的页面内容加载到当前页,再整体编译,不会单独编译 ,JSP动作标签中的include是属于动态包含,各页面独立编译,在运行进动态加载内容到当前页面

注:被包含的页面最好不要出现文档结构定义的标签

JavaBean对象(cn.lanqiao.entity包中的对象)

什么样的类称为JAVABean类:

  1. 这个类是public ;
  2. 属性必须私有的
  3. 必须提供一个无参造方法;
  4. 必须提供一个GET访问器和SET访问器;

满足以上4点的类称为JavaBean类 ;

十三、JSP内置对象(9)
out对象:向页面输出信息的对象 (JspWriter类型的对象,与Servlet中的PrintWriter类一样)
request :HttpServletRequest类的实例
response:HttpServletResponse类的实例
application:ServletContext类的实例
config:ServletConfig类的实例
page :页面对象(相当于Servlet中的this对象)
exception :Exception类的实例
session :HttpSession类的实例
pageContext :PageContext类的实例

pageContext :表示当前页面的上下文,以上9个对象都可以通过pageContext得到;是JSP中的域对象(所以JSP中有4个域对象),pageContext对象主要应用:存数据(只能在当前页面中用--不设作用域,可以设作用域,改变所存数据域范围),获取项目资源

pageContext.setAttribute("address", "北京", PageContext.PAGE_SCOPE);//当前页有效
 PageContext.PAGE_SCOPE :1
pageContext.setAttribute("address", "北京", PageContext.REQUEST_SCOPE);
等效于 request.setAttribute("address","北京");

pageContext.setAttribute("sex", "男", PageContext.SESSION_SCOPE); 等效于
session.setAttribute("sex","男")

 PageContext.APPLICATION_SCOPE :4

十四、JSP的四大域对象

request域对象

application域对象

session域对象

pageContext域对象

十五、分页

理解分页:数据比较大时,需要分页展示(不能将所有数据一次性加载)

分页需要参数:当前页数据,每页大小,当前页码,总记录数,总页数

public class Pager<T> {
	private int pagesize; //每页记录数;
	private int pageindex; //当前页;
	private int pages;//总页数;
	private int totals;// 总记录数;
	private List<T> data = new ArrayList<T>();
}

十六、EL表达式与JSTL

对JSP页面,原则只能出现标签(页面不要出JAVA程序逻辑的代码),所以在JSP中,SUN给出了新的语法 :EL表达式及JSTL

EL :expression language 表达式语法 ,语法:${} ,通过EL表达式可以从域对象中取数据,并提供简单运算,EL表达式中包含11个隐式对象

pageContext用来访问JSP的隐性对象(9个)
pageScopepage对象的MAP
requestScoperequest对象的MAP
sessionScopesession对象的MAP
applicationScopeapplication对象的MAP
initParam获取ServletContext对象初使化参数Map
param包含请求参数字符串的MAP
paramValues包含请求参数字符串数组的MAP
header包含请求头字符串的MAP
headerValues包含请求头字符串数组的MAP
cookie按名称存储请求附带的cookie的MAP

EL表达式提供功能有限,对于程序逻辑中用到的IF语句,循环等没有很好的实现,需要用JSTL补充EL表达式的不限,如果项目中只用EL表达式,不需要导入任何资源,如果用到JSTL的语法部分,在项目中必须导入JSTL标签库

JSTL:Java server pages standarded tag library

JSTL今天已成为JSP实际标准组件了;需要导入2个JAR包(jstl.jar,standard.jar)

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

十七、Cookie对象

cookie:不是内置对象;cookie是服务器写入到用户的数据,存贮在用户的电脑中,在服务器可以读写cookie中的数据; cookie的存贮,不同的浏览器处理方式是不一样的,IE浏览器以文本文件存贮, google,firefox以数据库方式存贮cookie(sqlite); cookie一向是不安全的(敏感的数据不要用cookie存);

cookie中的数据只能为字符串格式,大小安全值一般不能超8k;

cookie中一般存的数据:网站个人喜好配制信息,账号(记住密码),购物车

cookie分为临时cookie与持久cookie,临时cookie浏览器窗口关闭,cookie就自动销毁,设置存活期的cookie为持久cookie(哪怕存活期为1秒)

google:C:\Users\lenovo\AppData\Local\Google\Chrome\User Data\Default
IE:C:\Users\lenovo\AppData\Roaming\Microsoft\Windows\Cookies

web记住密码:网页中的记住密码的实现与窗体记住密是不一样的(将账号与密码写入文件中,再读文件设默认值即可),网页中,不能用js读取服务器写到用户端的cookie值;

十八、maven

maven :是一个项目构建工具,使用maven创建一个项目(JAVAEE的项目还是JAVASE项目),构建的项目结构更优化,maven构建的项目最大的优点是项目中依赖的jar包的管理

Eclispe已集成(自带)maven工具的插件,可以直接使用自带的maven,缺点:对maven工具的配制不方便; 推荐使用自己的maven工具

http://maven.apache.org/download.cgi

maven使用:

1:在Eclipse中配制自己的maven工具

2:配制maven

A、本地仓库

 我的本地仓库地址:E:\maven\repository
 <localRepository>E:\maven\repository</localRepository>

B、配制下载镜像站点(国内)

<mirror>
  <id>alimaven</id>
  <name>aliyun maven</name>
  <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
  <mirrorOf>central</mirrorOf>              
</mirror>

C、配制JRE的版本

<profile>
    <id>jdk-1.8</id>
    <activation>
        <activeByDefault>true</activeByDefault>
        <jdk>1.8</jdk>
    </activation>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
    </properties>
</profile>

maven 核心功能 :maven除了会重构项目录结构外,更核心的功能是JAR的管理

项目依赖的JAR包从仓库中自动获取(本地仓库 -- (本地私服)--- 中央仓库 ),所以使用maven构建项目,需要联网

3:使用maven 创建JAVAEE的项目[重点]

在Eclipse中看到的项目 目录结构
--mavenproject
  --src/main/java : java代码
  --src/main/resources : 放项目配制文件
  --src/test/java :放单元测试类
  --src/test/resources :放单元测试依赖的配制信息
  --libraries :项目依赖的jar包
    --jre
    --maven dependencies
   --src/main
    -- java :映射src/main/java目录的资源
    -- /resources 映射src/main/resources目录的资源
    --webapp
		--META-INF
		--WEB-INF
		  --web.xml
   --pom.xml mavenjar依赖配制文件

4:创建JAVAEE的项目

maven创建的工程三种类型:jar (JAVASE工程), pom :父工程,war :JAVAEE工程

正常创建JAVAEE的项目选择的工程类型:war,但我们不选择,原因此类型的工程在创建后,没有构建好WEB目录结构,所以创建JAVAEE的项目,也选择jar类型,再将转换为JAVAEE的项目

5、如何从maven仓库中下载JAR

https://mvnrepository.com/