jsp文件的头部标识代码是:
<%@ page language=“java” contentType=“text/html; charset=utf-8”
pageEncoding=“utf-8”%>
jsp的标签
<%! %> 定义变量和方法的标签,但是不能够在这里边执行jsp的程序
<% %> 程序代码的执行标签
<%= %> 这个是调用变量和方法的标签。
如下代码:
<%!
String name=“张三,你来呀”;
String getName(){
return “我就是张三的返回值”;
}
%>
<% out.println(this.name); %>
<%=
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”,“AA@qq.com”));
map.put(“102”,new Emp(“101”,“BB”,“123456”,“BB@qq.com”));
map.put(“103”,new Emp(“101”,“CC”,“123456”,“CC@qq.com”));
map.put(“104”,new Emp(“101”,“DD”,“123456”,“DD@qq.com”));}
//判断用户名和密码是否正确的方法
//判断的是用户的账号和密码,所以用户是参数进来的
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表达式的混合使用。
人事管理系统界面显示
<%
//使用for循环来遍历人事管理系统的信息
for(String key:DBUtil.map.keySet()){
%>
<%
}
%>
账号信息 | 用户名 | 密码 | 邮箱 |
---|---|---|---|
<% out.println(DBUtil.map.get(key).getAccount()); %> | <% out.println(DBUtil.map.get(key).getName()); %> | <% out.println(DBUtil.map.get(key).getPassword()); %> | <% out.println(DBUtil.map.get(key).getEmail()); %> |
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的文件。
文件里边的内容是:
login
/login.jsp
age
100
我再打开服务器发现运行login.jsp的地址的url是:http://localhost:8080/PersonnelExample/denglu.do
会发现页面的地址变成了/denglu.do了。
config的内置函数
通过上边的配置,config的内置函数有两个方法的使用如下:
config.getServletName()
config.getInitParameter(key)
config获取的servlet-name的值是:<%= config.getServletName() %>
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传递参数的方法:
修改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的变量
如下代码的配置:
testServlet
com.test.serv.servletTest1
<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 {
//创建数据集合
Listlist=new ArrayList();
ServletContext context=this.getServletContext();
//初始化数据
context.setAttribute(“list”,list);
}
在web.xml里边配置这个Servlet。
通过配置web.xml使项目在启动的时候就开始创建实例,web.xml的配置:
InitServlet
com.c.InitServlet
2
...省略其他
**
表单上传文件问题的解决
**
文件上传的条件是:
必须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 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 userList=(List)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(606024);
//将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的页面里边的代码是:
u
s
e
r
n
a
m
e
,
{username},
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>
<!-- 类似if和else的的标签形式 -->
<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的登录页面的代码:
用户名:<input type="test" class="username" name="username"/>
<br>
密码:<input type="password" class="password" name="password" />
<br>
<p id="tip"></p>
<button id="sub">登录</button>
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中配置过滤器:
charFilter
filters.CharFilter
charFilter
/*
获取过滤器在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中的配置代码是:
charset
UTF-8
设置字符编码是:
//从配置文件获取编码标准
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的时候或者是页面找不到的时候会触发过滤器。
则配置如下:
如果是response.sendError(404); 也会触发ERROR模式的filter。
多种模式的过滤器
如下代码就是多种模式的过滤器的web.xml的设置。
FilterDemo3 /test1.jsp ERROR Forward REQUEST留言板案例
过滤器当访问这个页面时进行的过滤。
过滤器和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中的配置代码是:
com.listener.TestListener
多个监听器
如果是多个监听器在web.xml中进行配置。那么执行的顺序和配置的顺序是一样的。
监听器获取配置文件里边的参数
在配置文件里边设置web.xml:
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是可以设置时间的:
1
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的输出流的图片,所以图片会显示,如下代码:
算术验证码
其实就是算术的表达式写入到图片里边。
如下代码:
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
com.google.code.kaptcha.servlet.KaptchaServlet
<!-- 设置宽度和高度,这里是以这个为列,其实还有很多其他的属性是可以进行设置的 -->
<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>
<init-param>
<!--session.setAttribute("kcode",生成好的验证吗)-->
<param-name>kaptcha.session.key</param-name>
<param-value>kcode</param-value>
</init-param>
</servlet>
Kaptcha /kaptcha.jpg
jsp中访问的页面是如下:
验证码的验证
验证码的验证比较重要。
验证码的验证过程是在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中进行配置