java web的基础技术与总结

jsp的基础知识

jsp的基础语法

jsp文件的头部标识代码是:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
复制代码

jsp的标签

<%! %> 定义变量和方法的标签,但是不能够在这里边执行jsp的程序

<% %> 程序代码的执行标签

<%= %> 这个是调用变量和方法的标签。

如下代码:

    <%! 
		String name="张三,你来呀";
		String getName(){
			return "我就是张三的返回值";
		}
	%>
	<hr>
	<% out.println(this.name); %>
	<hr>
	<%=
		this.getName()//这个结尾是不能够有分号的,这标签表示的是直接输出的意思
	%>
复制代码

定义变量和方法在<%! %>和<%%>的区别

<%! %>代码块里边的内容如果没有变化,只会第一次刷新时会被执行。需要注意的是,每次调用这个值都是上一次保存在浏览器里边的值。

但是 <% %>代码块只要刷新就会执行,不管内容是否改变都会被执行。

导入包

<%@page import="java.util.,java.text." %>

如下实例,网页显示时间:

       <%!
    		public String getNowTime(){
        		//日期格式化的类以及显示的格式
        		SimpleDateFormat formater=new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
        		//日期时间戳的获取
        		Date currentTime=new Date();
        		//将时间戳格式化并且返回
        		return formater.format(currentTime);
    	    }
    	%>
    	<%=getNowTime() %>
复制代码

jsp的内置对象

通过一个案例来说明jsp内置对象的一些方法。

人事系统登录的demo

用户类:###


package com.test.user;

//用户类的定义
public class Emp {
	private String account;
	private String name;
	private String password;
	private String email;
	
	//创建一个用户的构造函数
	public Emp(String account,String name,String password,String email) {
		this.account=account;
		this.name=name;
		this.password=password;
		this.email=email;
	}
	
	//get and  set methods
	public String getAccount() {
		return account;
	}

	public void setAccount(String account) {
		this.account = account;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

}
复制代码

db类,数据类:###

package com.test.db;

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

import com.test.user.Emp;

/*
 * 正常来说这应该是一个操作数据库的包。但是目前我们用它来人为的制作数据 
 * */
public class DBUtil {
	//静态的成员变量
	public static Map<String,Emp> map=new HashMap<String,Emp>();
	
	//创造数据
	static {
		map.put("101",new Emp("101","AA","123456","[email protected]"));
		map.put("102",new Emp("101","BB","123456","[email protected]"));
		map.put("103",new Emp("101","CC","123456","[email protected]"));
		map.put("104",new Emp("101","DD","123456","[email protected]"));
		
	}
	
	//判断用户名和密码是否正确的方法
	//判断的是用户的账号和密码,所以用户是参数进来的
	public static boolean selectEmpByAccountPassword(Emp emp) {
		Boolean flag=false;
		for(String key:map.keySet()) {
			Emp e=map.get(key);
			if(e.getAccount().equals(emp.getAccount())
					&& e.getPassword().equals(emp.getPassword())) {
				flag=true;
				break;
			}
		}
		return flag;
		
	}

}

复制代码

登录的jsp页面

<!-- 人事管系统的登录界面 -->
	<h3>人事管系统的登录界面</h3>
	<div class="form-module">
		<form action="control.jsp">
			<p>用户名:<input type="text" name="account" /></p>
			<p>密码:<input type="password" name="password" /></p> 
			<p><input type="submit" value="登录"/></p>
		</form>
	</div>
复制代码

处理登录的jsp页面

使用了jsp的内置函数request

<%
		/*request内置函数获取用户提交的信息以及http协议的信息,
		request.getParameter获取提交参数*/
		
		String account=request.getParameter("account");
		String password=request.getParameter("password");
		
		/*
		如果jsp想使用java程序,那么使用import导入进来直接使用即可。
		*/
		//用户信息
		Emp emp=new Emp(account,null,password,null);
		//将用户信息进行验证
		Boolean flag=DBUtil.selectEmpByAccountPassword(emp);
		if(flag){//验证通过,表示登录成功
			out.println("登录成功");
		}else{//验证失败,表示登录失败
			out.println("登录失败");
		}
	%>
复制代码

登录成功后jsp页面的显示

如下代码,是html与java表达式的混合使用。

    <h3>人事管理系统界面显示</h3>
	<hr>
	<table border="1"
	 cellspacing="0"
	 cellpadding="0"
	 width="800"
	 align="center">
		<tr>
			<th>账号信息</th>
			<th>用户名</th>
			<th>密码</th>
			<th>邮箱</th>
		</tr>
		<%
			//使用for循环来遍历人事管理系统的信息
			for(String key:DBUtil.map.keySet()){
		%>
			<tr>
				<td><% out.println(DBUtil.map.get(key).getAccount()); %></td>
				<td><% out.println(DBUtil.map.get(key).getName()); %></td>
				<td><% out.println(DBUtil.map.get(key).getPassword()); %></td>
				<td><% out.println(DBUtil.map.get(key).getEmail()); %></td>
			</tr>
		<%		
			}
		%>
	</table>


复制代码

request内置函数的方法

request.setAttribute("name","ren"); request.getRequestDispatcher("result.jsp").forward(request,response); request.getAttribute("name")

    //给request设置属性,用于各个页面进行共同使用
		request.setAttribute("name","ren"); 
		//自动跳转到某页面,并且把request和reqsponse传递过去。并且路径还不会发生改变。
		request.getRequestDispatcher("result.jsp").forward(request,response);


    //获取值是:
    <%= request.getAttribute("name") %>
复制代码

pageContext内置对象的使用

pageContext.forward("xxx.jsp?name=laohu"); 获取这个传递过来的参数值是: request.getParameter("name"); 包含其他页面的内置对象方法是: pageContext.include("xxx.jsp"); pageContext还可以获取一些其他的对象: pageContext.getRequest,pageContext.getSession...

session的使用

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

session和平时我们接触的session的使用方式是一样的,时间和关闭浏览器等方式可以让session失效。

配置login.jsp页面的xml

在web-info 文件夹下新建一个web.xml的文件。 文件里边的内容是:

<web-app>
<servlet>
	<!-- 定义一个servelet-name为login,并且这个login所指的jsp文件是/login.jsp -->
	<servlet-name>login</servlet-name>
	<jsp-file>/login.jsp</jsp-file>
	<!-- 给这个jsp设定的访问页面的初始化参数为如下name和value -->
	<init-param>
		<param-name>age</param-name>
		<param-value>100</param-value>
	</init-param>
</servlet>

<!-- 映射之前的配置,之前设定一个servlet-name为login,所对应的url地址 -->
<servlet-mapping> 
	<servlet-name>login</servlet-name>
	<url-pattern>/denglu.do</url-pattern>
</servlet-mapping>
</web-app>

复制代码

我再打开服务器发现运行login.jsp的地址的url是:http://localhost:8080/PersonnelExample/denglu.do
会发现页面的地址变成了/denglu.do了。

config的内置函数

通过上边的配置,config的内置函数有两个方法的使用如下: config.getServletName() config.getInitParameter(key)

config获取的servlet-name的值是:<%= config.getServletName() %>
	<br>
config获取的初始化参数是:<%= config.getInitParameter("age") %>
复制代码

exception内置函数的使用

在jsp页面中如果我们抛出了错误。如: throw new exception("xxx");

我们可以在页面的头部设置一个专门处理错误页面的文件,使用的关键字是errorPage="xxx.jsp",如下:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8" errorPage="error.jsp"%>
复制代码

所指定处理异常的页面,需要关键字来指定是处理异常的页面,关键字指定如下isErrorPage="true",如果不指定则不能够直接使用exception来捕获异常的错误信息,如下代码:

提示的错误是:<%= exception.getMessage() %>

复制代码

application内置函数

这里我们会用一个网站访问次数的案例进行说明: application的作用域。

    //application的使用
	Object count=application.getAttribute("count");
	if(count==null){//说明是第一次访问该网站
		application.setAttribute("count",1);
	}else{
		//把个数转变成整型
		int i=(Integer)count;
		//没访问一次就增加1
		application.setAttribute("count",i+1);
	}

复制代码

url上传递的参数

jsp中get传递参数的方法:

<td><a href="update.jsp?account=<%= DBUtil.map.get(key).getAccount()%>
	&&name=<%= DBUtil.map.get(key).getName()%> &&email=<%= DBUtil.map.get(key).getEmail()%>">修改</a></td>

复制代码

XML

有些过时了,所以不打算做笔记了。以后用到再说把。

servlet的使用

我们之前是使用jsp调用java的包来处理业务逻辑。但是这种方法不适合写接口,java本身程序无法直接进行连接的访问。而servlet就是来解决这个问题的。

第一个servlet程序

1,必须继承HttpServlet类。 2,重写两个方法。 如下代码:

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class servletTest1 extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//get的请求访问
		System.out.println("doGet方法");
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//post的请求访问
		System.out.println("doPost方法");
	}
	
}

复制代码

配置web.xml

我们需要给这个java的应用程序配置一个能够访问url路径。而这个配置是在webContent下的web-info下新建一个web.xml文件。

一个servlet标签代表一个servlet类。

servlet-name是定义一个虚拟的servlet类在xml文件使用的名,和具体的路径对应。

servlet-class:就是具体的servlet类。

servlet-mapping:定义好的servlet的变量名所映射的url路径。

servlet-url:servelt-name所对应的具体的路径。

路径地址是:http://ip:端口/项目名/servelt-name的变量

如下代码的配置:

   <servlet>
		<servlet-name>
			testServlet
		</servlet-name>
		<servlet-class>
			com.test.serv.servletTest1
		</servlet-class>
	</servlet>
	
	<servlet-mapping> 
	
		<servlet-name>
			testServlet
		</servlet-name>
		
		<url-pattern>
			/testServlet
		</url-pattern>
		
	</servlet-mapping>
复制代码

动态生成url

通过方法获取相关的url地址。 如下代码和注释:

        out.println(request.getScheme()+",");//获取协议
	out.println(request.getServerName()+",");//获取当前的ip
	out.println(request.getServerPort()+",");//获取当前的端口
	out.println(request.getServletContext().getContextPath());//获取项目名称
复制代码

servlet的生命周期

生命周期主要是分3个周期:

第一个周期是init(只有在第一次请求时会被调用)。

第二个周期是service(只要是请求都会调用这个)。

第三个周期是desctory。

/**
 * Servlet implementation class ServletTest
 * 虚拟路径可以用如下的方式进行配置@WebServlet("/ServletTest")
 */
@WebServlet("/ServletTest")
public class ServletTest extends HttpServlet {
	
	@Override
	public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
		System.out.println("每次只要请求这个页面就会被调用");
	}

	@Override
	public void destroy() {
		/*
		 * 只有阶段结束的时候才会被调用,并不是服务器关闭。
		 * 而是整个项目在服务器上移除的时候会被调用
		 * */
		System.out.println("desctory被调用");
	}

	@Override
	public void init() throws ServletException {
		/* 生命周期第一个周期是init 
		 * 只是第一次被打开的时候调用之后都不会被调用
		 * */
		System.out.println("init被调用");
	}
}
复制代码

请求与响应

在servlet的类里边,请求与响应,分别是浏览器对服务器和服务器对浏览器。 如下: HttpServletRequest request, HttpServletResponse response

servletContext 和 serveletConfigz的使用

servletContext 表示的是该项目的运行文件。 servletConfig表示的是这个项目文件的配置文件,web.xml这个文件。

在一个java文件里边进行设置,如下代码表示:

    
    //ServletContext表示的是当前的项目,那么在同一个项目下的不同的java文件下可以通过设置属性来进行数据共享
    ServletContext context=this.getServletContext();
    context.setAttribute("username","老胡");
复制代码

在另一个java文件里边进行获取进行使用,只要是在同一个项目里边就可以:

    //通过ServletContex来获取设置的属性数据
    ServletContext context=this.getServletContext();
    System.out.println("ServletContext:"+context);
    Object username=context.getAttribute("username");
    System.out.println("username"+username);

复制代码

转发与重定向

转发与重定向的使用如下代码:

    //生成随机数,如果随机数大于5则跳转成功页面,否则是失败的页面
	Random r=new Random(1);
	int i=(int)r.nextInt(10);
	System.out.println(i);
	if(i<6) {
		//跳转到成功的页面,转发
		request.getRequestDispatcher("/success.jsp").forward(request,response);
		
	}else {
		//如果失败就是重定向页面,在设定路径的时候要加上项目名称,重定向
		response.sendRedirect("/serv/error.jsp");
	}
复制代码

转发并不会跳转到具体的页面,浏览器的地址还是原始的地址,虽然页面已经跳转了,如下图:

重定向会跳转到具体的页面,浏览器的地址栏看的出。

转发与重定向参数的问题

转发的参数携带是使用request.setAttribute();进行设置的,获取是getAttribute()进行获取的。所以相对来说简单些。 具体说下,重定向参数的设置和获取,

如果说java文件之间的跳转: 如下代码:

    ServletContext context=request.getServletContext();
	context.setAttribute("username","huminggui");
	response.sendRedirect("/serv/ServletTest4");
复制代码

如果是跳转到jsp页面,那么就是用application进行获取,如下:

    //重定向参数的获取和设置
	//携带参数用的是appliction或者是requestContext
	ServletContext context=request.getServletContext();
	context.setAttribute("username","huminggui");
	response.sendRedirect("/serv/success.jsp");
复制代码

jsp页面

<%
		out.print(application.getAttribute("username"));
	%>
复制代码

登录注册的案例

User类的创建:

User类的创建:

    //这个是User类的关键字
    private String username;
	private String nickname;
	private String password;
	private String sex;
	private String hobby;
	private String path;


复制代码

InitServlet

初始化用户数据表。

并且将这个用户数据表保存在ServletContext里边。

项目刚开始的时候就初始化上边的数据。是需要在web.xml里边进行配置的。

InitServlet的代码如下:

    @Override
	public void init() throws ServletException {
		//创建数据集合
		List<User>list=new ArrayList<User>();
		ServletContext context=this.getServletContext();
		//初始化数据
		context.setAttribute("list",list);
		
	}

复制代码

在web.xml里边配置这个Servlet。

通过配置web.xml使项目在启动的时候就开始创建实例,web.xml的配置:

    <servlet>
		<servlet-name>InitServlet</servlet-name>
		<servlet-class>com.c.InitServlet</servlet-class>
		<!--启动的时候创建实例-->
		<load-on-startup>2</load-on-startup> 
	</servlet>
	
	...省略其他
复制代码

表单上传文件问题的解决

文件上传的条件是:

  • 必须post方式
  • name属性必须有并且type="file"
  • form表单的属性enctype的值必须是multipart/form-data

这个写错好几回:

enctype="multipart/form-data"

需要用到2个jar的包。

在java中如果使用第三方的jar包,则需要把jar包放到web-info-->lib文件夹里边,然后再代码中就可以直接调用了。

两个jar包的使用导致了在接收form表达传递过来的数据无法用之前的request进行接收,具体的代码和注释如下显示:

@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			//创建一个磁盘文件工厂对象,用的是第三方的jar包
			DiskFileItemFactory dfif=new DiskFileItemFactory();
			//创建一个解析request的核心类,参数是磁盘文件工厂
			ServletFileUpload slfu=new ServletFileUpload(dfif);
			//解析request,返回request获取的表单的集合,FileItem是jar包给我们提供的类
			List<FileItem> list =slfu.parseRequest(request);
			
			//遍历这个集合判断哪个是上传的文件,哪个是普通的表单元素
			for(FileItem fileItem:list) {
				
				if(fileItem.isFormField()) {
					String name=fileItem.getFieldName();//获取表单的name属性
					String value=fileItem.getString("utf-8");//获取表单的值
					System.out.println(name+":"+value);
				}
			}
		} catch (FileUploadException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
复制代码

第三方的jar包分别是,如下代码和截图:

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

复制代码

截图:

随机生成文件名的方法

public static String getFielUUIDName(String filename) {
		//获取文件的后缀
		int idx=filename.lastIndexOf(".");//获取最后一个点的位置
		String ex=filename.substring(idx);//最后一个点开始截取的内容
		//创建随机字符串,但是随机字符串中间会有-,去掉-,然后再把.jpg的内容连接
		String randomFileName=UUID.randomUUID().toString().replace("-", "")+ex;
	
		return randomFileName;
	}
}
复制代码

文件上传的实现

如下代码和注释:

                     //如果是文件则在这里进行处理
					//获取提交上来的文件的文件输入流
					String fname=fileItem.getName();
					//获取文件输入流,就是上传文件的输入流
					InputStream is=fileItem.getInputStream();
			
					//获取upload这个文件在项目的位置,getServletContext()是获取当前的项目名称
					String uploadPath=this.getServletContext().getRealPath("/upload"); 
					//获取.metadata之前的路径
					int start=uploadPath.indexOf(".metadata");
					String startPath=uploadPath.substring(0,start);
					//获取项目的名称
					String projectName=request.getContextPath().substring(1);
					//拼接图片上传的地址
					String url=startPath+projectName+"\\"+"upload";
					
					//文件的名称是通过其他工具类生成的
					String ex=FileUUIDName.getFielUUIDName(fname);
					//输出的路径是
					String outPath=url+"\\"+ex;
					
					//定义一个输出流
					OutputStream os=new FileOutputStream(outPath);
					//输出流写入文件
					int len=0;
					byte [] b=new byte[1024];
					while((len=is.read(b))!=-1) {
						os.write(b,0,len);
					}
					is.close();
					os.close();
	
				

复制代码

用户名密码以及文件的校验

校验其实是在添加数据到数据文件的时候进行的一个验证。

如下是在Servletjava中进行的操作代码:

//把创建好的User实例存储到servletContext中
			ServletContext context=this.getServletContext();
			//在服务器刚启动时存储了list的集合,现在需要把这个集合进行更新
			List<User> userList=(List<User>)context.getAttribute("list");
			//校验用户名是否已经在数据集合里边了
			for(User user:userList) {
				if(user.getUsername().equals(map.get("username"))) {
					request.setAttribute("msg","用户名已经存在了");
					request.getRequestDispatcher("/regist.jsp").forward(request, response);
					return;
				}
			}

复制代码

在regist.jsp中的代码是如下:

        String msg="";
	//是否有错误的信息
	if(request.getAttribute("msg")!="" && request.getAttribute("msg")!=null){
		msg=(String)request.getAttribute("msg");
	}
复制代码

用户名保存在cookie里边

首先通过提交上来的参数,判断是否需要将数据保存cookie。

cookie的使用,可以参考如下代码:

    String remember=request.getParameter("remember");
    //如果remember为true说明记住用户名的选项是勾住的
    if(remember.equals("true")) {
    	Cookie cookie=new Cookie("username",user.getUsername());
    	//设置cookie保存的路径
    	cookie.setPath("/UserDmeo");
    	//设置cookie保存的时间以秒为单位
    	cookie.setMaxAge(60*60*24);
    	//将cookie保存在response中
    	response.addCookie(cookie);
    }
复制代码

在jsp的页面中获取cookie的使用:

为了能够更

public class CookieUtils {
	public static Cookie getCookie(Cookie [] cookies,String name) {
		//传递进来的cookies数组不能够为null
		if(cookies==null) {
			return null;
		}else {
			//说明cookies是存在的,for循环cookies,来判断哪个是我们需要的cookie
			for(Cookie cook :cookies) {
				//如果cookie的键是一样的,说明是存在的
				if(cook.getName().equals(name)) {
					//返回这个cook
					return cook;
				}
				
			}
			return null;
		}
	}

}


复制代码

在jsp中使用cookie工具类并且进行赋值的操作如下:

    //获取所有的cookie内容	
	Cookie[] cookies=request.getCookies();
	//调用第三方的工具来寻找到自己需要的cookie
	Cookie cookie=CookieUtils.getCookie(cookies,"username");
	if(cookie!=null){
		uname=(String)cookie.getValue();
	}

复制代码

El表达式

保存在request作用域里边的变量可以直接通过el表示在另外一个页面上获取。

如下代码:

	//把值保存在request的作用域上边
		request.setAttribute("username",username);
		request.setAttribute("age",age);
		
		//跳转到2.jsp中在这个页面用el的表达式获取这些数据
		request.getRequestDispatcher("/2.jsp").forward(request,response);
复制代码

在跳转到的2.jsp的页面里边的代码是:

	${username},${age}

复制代码

jstl 和 el

入门与常用的标签

首先是需要一个jstl的一个jar包。

然后就是jsp页面上标签的几个固定的写法:

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

复制代码

set out rmove的基本使用如下:


    <!-- 之所以有这些标签是因为上边的prefix有指定这个标签,然后是scope的值可以是request、session等作用域。 -->
	<c:set var="username" value="张三" scope="request"></c:set>
	<c:out value="${username}"></c:out>
	<hr>
	<c:remove var="username" />
	<c:out value="${username}"></c:out>
	
	
复制代码

if标签和choose标签:

如下代码:

<!-- 这里在判断的时候张三居然是不需要字符串的表现形式的 -->
	<c:if test="${username==张三}">
		我是张三
	</c:if>
	
	<!-- 类似ifelse的的标签形式 -->
	
	<c:choose>
		<c:when test="${age==13}">
			13岁
		</c:when>
		<c:otherwise>
			不是13岁
		</c:otherwise>
	</c:choose>
	
	

复制代码

jstl的forEach的使用:

我们这里会做一个小小的案例,就是在页面上显示一个数据的表格。

可以在另外一个页面使用这些数据,如下代码是产生数据的编码:

//创建一个map的数据,这个map里边的数据是一个产品的name、产地、价格
		Map<String, Object> map=new HashMap<String, Object>();
		//在这个map添加其他的数据
		map.put("name","联想电脑");
		map.put("address","北京");
		map.put("price",4999);
		//创建第二个对象
		Map<String, Object> map2=new HashMap<String, Object>();
		map2.put("name","神州");
		map2.put("address","南京");
		map2.put("price",3999);
		
		//把map这个对象放入打list里边
		List<Map<String,Object>> list=new ArrayList<Map<String, Object>>();
		list.add(map);
		list.add(map2);
		request.setAttribute("list",list);
		//数据添加到list里边后,页面跳转到5.jsp页面
		request.getRequestDispatcher("/5.jsp").forward(request,response);

复制代码

登录的实例使用ajax

ajax的优点是局部刷新并不需要页面的提交就可以进行相关的操作。

jsp的登录页面的代码:

<script type="text/javascript" src="resources/js/jq.js"></script>
<body>

	用户名:<input type="test" class="username" name="username"/>
	<br>
	密码:<input type="password" class="password" name="password" />
	<br>
	<p id="tip"></p>
	<button id="sub">登录</button>
	
</body>
<script>
	$(function(){
		$("#sub").click(function(){
			/* console.log($(".username").val()); */
			$.ajax({
				url:"http://localhost:8080/ELDemo/loginValidate",
				type:"post",
				data:{
					username:$(".username").val(),
					password:$(".password").val()
				},
				dataType:"json",
				success:function(res){
					console.log(res);
					if(res.flag==true){
						//成功,跳转到成功的页面
						window.location.href="/ELDemo/success.jsp"
					}else{
						//失败,提示错误信息
						$("#tip").html("用户名或密码错误").css("color","red");
					}
				}
			});
		});
	});
</script>

复制代码

java代码是: json是需要另外的jar包支持的。

    String username=request.getParameter("username");
    String password=request.getParameter("password");
    System.out.println(username+","+password);
    JSONObject res;
    //不管是验证通过还是失败都要给前端你返回一个结果
    if(username.equals("11") && password.equals("11")) {
    	//表示的是验证通过
    	res=new JSONObject("{flag:true}");
    }else {
    	//表示的验证失败
    	res=new JSONObject("{flag:false}");
    }
    //返回数据给前端,把json转成字符串然后转成byte格式。
    response.getOutputStream().write(res.toString().getBytes("utf-8"));

复制代码

过滤器

定义过滤器和配置过滤器

代码:

public class CharFilter implements Filter {

	@Override
	public void destroy() {
		//过滤器销毁

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		//根据xml的设置文件进行访问,只要满足条件就会执行这里边的操作。
		
		//表示调用下一个过滤器
		chain.doFilter(request,response);

	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		//过滤器就是刚开始项目启动的时候就会执行的,只启动一次

	}

}


复制代码

web.xml中配置过滤器:

 <filter>
  	<filter-name>charFilter</filter-name>
  	<filter-class>filters.CharFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>charFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
复制代码

获取过滤器在xml中的配置

在web.xml配置文件中是可以设置多个属性和值的,如下代码:

首先一定要定义的config是FilterConfig。

private FilterConfig config;
复制代码

其次在filter初始化的时候,进行web.xml的获取,如下代码:

	public void init(FilterConfig config) throws ServletException {
		//过滤器就是刚开始项目启动的时候就会执行的,只启动一次
		this.config=config;
	}


复制代码

最后是从获取到的配置对象里边获取响应的属性:

String ver=config.getInitParameter("version");
复制代码

过滤器实现字符集编码问题

具体是用的是哪个编码,最好是设置在配置文件里边。

具体代码如下: web.xml中的配置代码是:

    <init-param>
  		<param-name>charset</param-name>
  		<param-value>UTF-8</param-value>
  	</init-param>

复制代码

设置字符编码是:

    //从配置文件获取编码标准
    String charset=config.getInitParameter("charset");
    request.setCharacterEncoding(charset);

复制代码

登录安全的控制

但是下边的代码只是逻辑上是可以作为参考的,但是事实上可能并不是那么的成立。


        //获取session,查看session里边是否有username,如果存在则是表示登录,否则表示没有登录
		if(hrequest.getSession().getAttribute("username")==null) {
			//如果是null表示没有登录,这个时候返回到登录界面
			hresponse.sendRedirect(hrequest.getContextPath()+"/login.jsp");
			//hrequest.getRequestDispatcher("/login.jsp?flag=1").forward(hrequest,hresponse);
			return;
		}else {
			//表示已经登录那么就执行下一步操作即可
			//表示调用下一个过滤器
			chain.doFilter(hrequest,hresponse);
			return;
		}


复制代码

过滤器的3种设置方式

就是过滤器在使用的时候针对forward的方式、include的方式,以及error错误页面的方式。4种方式都说在web.xml里边进行设置的。

默认是request方式。

forward

include

error

正常情况下如果不设置对forward的方式是不会被过滤的。

如下代码:

//如果设置为forward的模式,那么正常的url访问是不会触发过滤器的。
只有在request.getRequestDispatcher().forward();才会触发过滤器
//如果是include
则只有在
<jsp:include page="/test1.jsp" ></jsp:include>

//如果是错误的触发是,错误代码是404的时候或者是页面找不到的时候会触发过滤器。
则配置如下:

<filter>
  	<filter-name>FilterDemo3</filter-name>
  	<filter-class>filter.TestFileter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>FilterDemo3</filter-name>
  	<url-pattern>/test1.jsp</url-pattern>
  	<dispatcher>ERROR</dispatcher>
  </filter-mapping>
  
  <error-page>
  	<error-code>404</error-code>
  	<location>/test1.jsp</location>
  </error-page>

如果是response.sendError(404); 也会触发ERROR模式的filter。


复制代码

多种模式的过滤器

如下代码就是多种模式的过滤器的web.xml的设置。


 <filter-mapping>
  	<filter-name>FilterDemo3</filter-name>
  	<url-pattern>/test1.jsp</url-pattern>
  	<dispatcher>ERROR</dispatcher>
  	<dispatcher>Forward</dispatcher>
  	<dispatcher>REQUEST</dispatcher>
  </filter-mapping>
  
复制代码

留言板案例

过滤器当访问这个页面时进行的过滤。

过滤器和node的中间件极度相似,也是一个过滤器完了后调用另外一个过滤器。

监听器

监听器入门

监听器主要是针对3个大的方面进行监听,一个context、sesssion、request。以及他们的attribute属性的监听的接口。

实现他们得监听器的接口,然后再web.xml里边进行注册。

第一个监听器的实例:

web服务器的开启和关闭时的监听器的代码:

public class TestListener implements ServletContextListener {

	@Override
	public void contextDestroyed(ServletContextEvent context) {
		System.out.println("ContextListener desctory...");

	}

	@Override
	public void contextInitialized(ServletContextEvent context) {
		System.out.println("contextListener init ....");
		

	}

}

复制代码

在web.xml中的配置代码是:

<listener>
  	<listener-class>com.listener.TestListener</listener-class>
</listener>

复制代码

多个监听器

如果是多个监听器在web.xml中进行配置。那么执行的顺序和配置的顺序是一样的。

监听器获取配置文件里边的参数

在配置文件里边设置web.xml:


 <context-param>
  	<param-name>app_name</param-name>
  	<param-value>bigbig</param-value>
  </context-param>

复制代码

Listener中的代码: //获取配置文件中配置的属性

	String appName=(String)context.getServletContext().getInitParameter("app_name");
	
复制代码

session的监听器

当一个新的浏览器打开的时候,每次创建一个新的session。

public class httpSessionTest implements HttpSessionListener {

	@Override
	public void sessionCreated(HttpSessionEvent hse) {
		//创建的时候的id和时间
		String sessionId=hse.getSession().getId();
		Date createTime=new Date(hse.getSession().getCreationTime());
		System.out.println("sessionId:"+sessionId+","+"time:"+createTime);
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent hse) {
		//销毁的是哪个sessionId
		System.out.println("sessionId:"+hse.getSession().getId());
	}

}

复制代码

配置文件中session是可以设置时间的:

  <session-config>
  	<session-timeout>1</session-timeout>
  </session-config>
  
复制代码

attribute的监听器

request 的代码是如下的:

public class TestRequestAttribute implements ServletRequestAttributeListener {

	@Override
	public void attributeAdded(ServletRequestAttributeEvent srae) {
		//添加属性的时候
		String name=srae.getName();
		String value=(String)srae.getValue();
		System.out.println("name:"+name+","+"value:"+value);
	}

	@Override
	public void attributeRemoved(ServletRequestAttributeEvent arg0) {
		//删除属性的时候

	}

	@Override
	public void attributeReplaced(ServletRequestAttributeEvent arg0) {
		//修改属性的时候

	}

}
复制代码

需要在刚问的文件里边进行如下的操作:

    request.setAttribute("username","laohu"); 

复制代码

java验证码

生成验证码的工具方法

这个是生成验证码的工具方法。

主要是注意两点: 1,图片验证码在流中,2,返回的code只是字符串。

如下代码:

public class CreateValidateCode {
	
	//验证码的生成
	/*
	 * response 主要是用来输出图片的流
	 * */
	public static String createCodeImage(HttpServletResponse response) {
		//可以不把字符类型组件然后转变成字符串类型
		StringBuilder builder=new StringBuilder();
		
		for(int i=0;i<4;i++) {
			builder.append(randomChar());
		}
		String code=builder.toString();
		
		//设置图片的width和height
		int width=120;
		int height=25;
		
		//设定一个图片的缓存流,图片的高度和宽度,以及图片的背景。
		BufferedImage bi=new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
		//获取这个缓存流的绘制对象
		Graphics2D g=bi.createGraphics();
		//设置文字的大小和字体
		Font font=new Font("微软雅黑",Font.PLAIN,20);
		//颜色
		Color color=new Color(0,0,0);
		//设置字体
		g.setFont(font);
		//设置颜色
		g.setColor(color);
		//设置背景颜色
		g.setBackground(new Color(226,226,240));
		//开始绘制对象
		g.clearRect(0, 0, width, height);
		//获取这个绘制对象的上下文
		FontRenderContext context=g.getFontRenderContext();
		//获取绘制的矩形
		Rectangle2D bounds=font.getStringBounds(code,context);
		//计算坐标和间距
		double x=(width-bounds.getWidth())/2;
		double y=(height-bounds.getHeight())/2;
		double ascent=bounds.getY();
		double baseY=y-ascent;
		//绘画
		g.drawString(code, (int)x, (int)baseY);
		//结束绘制
		g.dispose();
		
		//最重要的一步是这个绘制好的图片输出的位置
		try {
			//把图片以jpg的格式写入到输出流里边
			ImageIO.write(bi,"jpg",response.getOutputStream());
			//刷新响应流
			response.flushBuffer();
		}catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		
		
		
		
		
		return code;
	}
	
	
	private static char randomChar() {
		String coded="QWERTYUIOPLKJHGFDSAZXCVBNM1234567890";
		Random r=new Random();
		//只能在字符串的长度内才可以
		//在允许的随机生成的范围内才可以
		 return coded.charAt(r.nextInt(coded.length()));
	}
}

复制代码

jsp页面访问这个生成验证码图片的工具类,并且把输入流传递过去作为参数:

代码如下:

<%@ page language="java" import="util.*" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	//首先要清楚浏览器的缓存,目的是为了情况浏览器的缓存,因为浏览器对网页是有记忆的,否则的话请求 会无法刷新。
	response.setHeader("pragma","no-cache");
	response.setHeader("cache-control","no-cache");
	response.setHeader("expires","0");
	
	//调用编写的生成验证码工具,把response的输出流给它,就会对接上输出流。
	String code=CreateValidateCode.createCodeImage(response);
	session.setAttribute("code",code);
	
	//如何解决输出流getOutputStream异常问题。
	out.clear();
	out=pageContext.pushBody();

%>

复制代码

前端jsp页面获取这个输入流并且进行图片的显示:

重点理论:img的src属性获取的是jsp的输出流的图片,所以图片会显示,如下代码:

<body>
	<img src="code.jsp" id="code" /><a href="javascript:;" 
	onclick="changeCode()">看不清?点击刷新</a>
	
	
	
</body>
<script>

	function changeCode(){
		//每次点击就会刷新这个页面,因为浏览器有记忆的功能,地址不一样才会被刷新
		document.getElementById("code").src="code.jsp?"+new Date().getTime();
	}
		
</script>

复制代码

算术验证码

其实就是算术的表达式写入到图片里边。

如下代码:

public static String computedCode(HttpServletResponse response) {
		
		//算术表达式
		Random r=new Random();
		int number1=(int)(Math.random()*10+1);
		int number2=(int)(Math.random()*10+1);
		//符号
		int isIChar=r.nextInt(3);
		
		String iChar="";
		int endNumber=0;
		switch(isIChar) {
			case 0:
				iChar="+";
				endNumber=number1+number2;
				break;
			case 1:
				iChar="-";
				endNumber=number1-number2;
				break;
			case 2:
				iChar="×";
				endNumber=number1*number2;
				break;
			default:
				
		}
		
		//需要写入到图片里边的字符串拼接起来
		String strValue=number1+" "+iChar+" "+number2+"=?";
		//System.out.println(strValue);
		//System.out.println(endNumber);
		
		//开始绘制图片
		//设置图片的width和height
		int width=120;
		int height=25;
		
		//设定一个图片的缓存流,图片的高度和宽度,以及图片的背景。
		BufferedImage bi=new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
		//获取这个缓存流的绘制对象
		Graphics2D g=bi.createGraphics();
		//设置文字的大小和字体
		Font font=new Font("微软雅黑",Font.PLAIN,20);
		//颜色
		Color color=new Color(0,0,0);
		//设置字体
		g.setFont(font);
		//设置颜色
		g.setColor(color);
		//设置背景颜色
		g.setBackground(new Color(226,226,240));
		//开始绘制对象
		g.clearRect(0, 0, width, height);
		//获取这个绘制对象的上下文
		FontRenderContext context=g.getFontRenderContext();
		//获取绘制的矩形
		Rectangle2D bounds=font.getStringBounds(strValue,context);
		//计算坐标和间距
		double x=(width-bounds.getWidth())/2;
		double y=(height-bounds.getHeight())/2;
		double ascent=bounds.getY();
		double baseY=y-ascent;
		//绘画
		g.drawString(strValue, (int)x, (int)baseY);
		//结束绘制
		g.dispose();
		
		//最重要的一步是这个绘制好的图片输出的位置
		try {
			//把图片以jpg的格式写入到输出流里边
			ImageIO.write(bi,"jpg",response.getOutputStream());
			//刷新响应流
			response.flushBuffer();
		}catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		
		return strValue;
	}

复制代码

框架实现验证码

需要第三方jar包 : kaptcha-2.3.2.jar

框架实现验证码主要分成两部分:

一部分当然是jsp页面的访问。

另一部分是重点是:web.xml的配置。

配置如下: jar包里边的包都是固定的,所以有些内容也是固定的。

    <!--  kaptcha的配置 -->
  <servlet>
  	<servlet-name>Kaptcha</servlet-name>
  	<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
  	
  	<!-- 设置宽度和高度,这里是以这个为列,其实还有很多其他的属性是可以进行设置的 -->
  	<init-param>
         <param-name>kaptcha.image.width</param-name>
         <param-value>100</param-value>
    </init-param>
    <init-param>
       <param-name>kaptcha.image.height</param-name>
       <param-value>40</param-value>
    </init-param>
    
   <!--  用框架设置好的验证码,保存在session里边的key值是在这里设置的 -->
  	 <init-param>
        <!--session.setAttribute("kcode",生成好的验证吗)-->
        <param-name>kaptcha.session.key</param-name>
        <param-value>kcode</param-value>
     </init-param>
    
  	</servlet>
  
  <servlet-mapping>
  	<servlet-name>Kaptcha</servlet-name>
  	<url-pattern>/kaptcha.jpg</url-pattern>
  </servlet-mapping>

复制代码

jsp中访问的页面是如下:

<img src="http://localhost:8080/ValidateCodeDemo/kaptcha.jpg">

复制代码

验证码的验证

验证码的验证比较重要。

验证码的验证过程是在servlet的类里边进行验证的,如下代码实现:


protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		//设置请求字符集
		request.setCharacterEncoding("utf-8");
		//设置响应字符集
		response.setCharacterEncoding("utf-8");
		//获取浏览器输入流的对象,用户向客户端输出内容
		PrintWriter out=response.getWriter();
		//获取传递过来的code
		String code=request.getParameter("code");
		System.out.println(code);
		//获取从session对象里边获取的code(第三工具提供的)这个是固定的写法,但是web.xml不能设置session标签了。
		//用常量比较好。如果web.xml有设置则直接写设置的key也可以。
		//但是最好不要用变量,因为web.xml改变则这里代码也得改变。
		String sessionCode
		=(String)request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
		System.out.println(sessionCode);
		if(sessionCode!=null && code!=null){
			//这个方法是不区分大小写的equalsIgnoreCase
			if(code.equalsIgnoreCase(sessionCode)) {
				out.print("success");
			}else {
				out.print("fail");
			}
		}else {
			out.print("fail");
		}
	}

}

复制代码

前端jsp页面的代码实现,如下:

这里有用到jq刷新验证码和用ajax提交页面请求:

$(function(){
		
		$("#code").click(function(){
			$(this).attr("src","http://localhost:8080/ValidateCodeDemo/kaptcha.jpg?"+new Date().getTime());
		});
		
		$("#btn").click(function(){
			$("#msg").html("");
			$.ajax({
				url:"http://localhost:8080/ValidateCodeDemo/loginServlet",
				type:"post",
				data:{
					code:$("#kcode").val()
				},
				success:function(res){
					if(res==="success"){
						alert("验证码输入成功");
					}else{
						$("#msg").html("验证码输入错误,请重新输入");
						$("#kcode").html("").focus();
					}
				}
			});
		});
	});
复制代码

intellij IDE的使用技巧

快捷键

ctrl+alt+s 设置页面 ctrl+shift+enter 自动补充方法或者其他结构 psvm 主方法 sout 是输出语句 fori for循环的快捷键

shift+f6(fn键按住) 是修改类的名字,会同时修改所有的使用这个类的名称,只限在当前文件下。属性也是同样的方法进行修改。

ctrl+alt+m 提取某一块为一个方法 alt +up/down 是一个一个方法的选中 shift+shift 查询 ctrl+h 当前类的继承关系的窗口 ctrl+f 当前页面的内容查询

两个设置的快捷键: ctrl+alt+s ctrl+shift+alt+s

文件和目录相关的

.iml 是工程的配置文件。 out 是工程的输出语句

web项目的操作

创建时选择 web application

==在idea中的project可以创建多个module。一个module可以代表一个应用。

new-->module 就可以在当前项目下进行创建。

单点登录

暂时不想继续了,学起来费劲。

淘宝和天猫只要登录一端,另一端就自动登录了,这个就是单点登录。

单点登录的简称是sso。

主要的技术

Jsp Servlet HttpClient cookie Thread 等技术。

把jar包加入到module里边

ctrl+alt+shift+s 打开设置页面-->libraries--选择+号-->选择java-->选择要添加的jar包。选择后会弹出把这些jar包,给哪个模块使用。选择相应的模块后,点击apply应用。有几个模块需要添加的jar包的,就做几个操作。

====================添加tomcat: 每一个模块对应一个server。

配置tomcat。 tomcat configurations--->选择+号--->Tomcat server--->local--->改变端口号--->deployment--->atifact(这一步最重要,选择你的模块)。

这么配置完后就是你的模块对应相应的本地端口。

判断登录成功

这里使用到了HttpServlet。

Object.equals(a,b);a和b相等就会返回true。

文档的导入导出

WEB-INF 下边的jsp程序是无法直接访问的。

jsp文件供其他jsp文件使用的配置

在web.xml中进行配置


复制代码

猜你喜欢

转载自juejin.im/post/5e9669e4f265da47c917088c
今日推荐