数值类型
tinyint(m)1个字节 范围(-128~127)smallint(m)2个字节 范围(-32768~32767)mediumint(m)3个字节 范围(-8388608~8388607)int(m)4个字节 范围(-2147483648~2147483647)bigint(m)8个字节 范围(±9.22*10的18次方)浮点型(float和double)
float(m,d)单精度浮点型 8位精度(4字节) m总个数,d小数位double(m,d)双精度浮点型 16位精度(8字节) m总个数,d小数位字符类型
char(n)固定长度,最多255个字符varchar(n)固定长度,最多65535个字符tinytext可变长度,最多255个字符text可变长度,最多65535个字符mediumtext可变长度,最多2的24次方-1个字符longtext可变长度,最多2的32次方-1个字符日期时间类型
date日期 ‘2008-12-2’time时间 ‘12:25:36’datetime日期时间 ‘2008-12-2 22:06:44’timestamp自动存储记录修改时间注:distinct字段: 去除字段的重复记录
select distinct 字段名 from 表名 where 条件;IFNULL(字段,0):函数表示:如果字段是空的,用0代替
select 字段1+IFNULL(字段2,0),字段名 from 表名;concat()函数:连接字段,形成字符串
select concat(字段名,'的工资是',字段1+IFNULL(字段2,0),'美元' )from 表名;order by: 字段 asc : 升序排序,默认升序:如果不写,默认升序。 字段 desc: 降序排序,desc必须写。如果有多个排序条件:order by 字段1 desc,字段2 asc,…
order by:排序count()函数:
统计有多少条记录
语法:select count(*)/count(1) from 表名;统计某个字段不为空的记录
语法:select count(字段) from from 表名;sum()函数:统计某个字段的总和
语法:select sum(字段) from 表名;avg()函数:统计某个字段的平均值
语法:select avg(字段) from 表名;max()函数:统计某个字段的大值
语法:select max(字段) from 表名;min()函数:统计某个字段的小值
语法:select min(字段) from 表名;语法:group by 要分组的字段
select * from 表名 where 条件 group by 分组 having 对聚合函数进行过滤 order by 排序 limit 分页having和where的区别?:
01)having:对聚合进行过滤,写在group by 后面,千万不能写where中!!
02)where:对普通字段进行过滤
关键字:like
查询不包含某个字符
select * from student where 列名 not like'王%'查询包含某个字符
select * from student where 列名 like'王%'limit:查询指定的记录
语法:limit 起始行-1,行数
select * from 表名 limit 起始行-1,查询几行记录;公式:
查询前5条 每一页显示5行 pageSize=5 currentPage:显示第几页 pageSize:每页显示几行 select * from 表名 limit (currentPage-1)*pageSize,pageSizeunion 去除重复记录
union all 不去除重复记录
select 字段名 from 表名1 union select 字段名 from 表名2做外链接把左表作为主表
select 字段名 from 左表名 left join 右表 on 左表主键 = 从表外键;注:localhost代表只有本机可以登录,远程不可以,也可以省掉 [ @‘localhost’ ]
create user '用户名'@'localhost' identified by '密码';注:这是把所有的权限授权给这个用户并允许这个用户给其他用户授权,[ with grant option ] 代表此用户可以给其他用户授权
grant all on *.* to '用户名'@'localhost' with grant option;在控制台使用mysqldump命令可以用来生成指定数据库的脚本文本,但要注意,脚本文本中只包含数据库的内容,而不会存在创建数据库的语句!所以在恢复数据时,还需要自已手动创建一个数据库之后再去恢复数据。
未完待续…
01)DriverManager类:加在数据库驱动得到数据库的连接对象
02)Connection接口:表示连接对象,创建这个对象成功,表示数据库连接成功
03)Statement接口:sql语句执行器 增删改:executeUpdate(sql) 查:executeQuery(sql)
04)ResultSet接口:表示一个结果及对象
05)PreparedStatement子接口: 继承自Statement,预编译对象,使用占位符
ResultSetMetaData rsmd= rs.getMetaData(); 得到rs这个结果集列的信息6)CallableStatement 是PreparedStatement子接口,子程序【存储过程,函数】,调用或执行数据库存储过程
{?= call <function-name>[(<arg1>,<arg2>, ...)]} {call <procedure-name>[(<arg1>,<arg2>, ...)]}连接池
javax.sql.* DataSource连接池的一个标准 c3p0 实现了DataSource这个接口
ComboPooledDataSource ds=new ComboPooledDataSource(); 自动到src下找c3p0-config.xml,读取这个文件中的连接信息 ds.getConnection();使用JDBC连接数据库进行查询的步骤:
1) 导入驱动程序jar包 :mysql-connector-java-5.1.7-bin.jar
2) 加载驱动程序 Class.forName(“com.mysql.jdbc.Driver”);
3) 获取数据库连接对象:Connection
4) 获取发送SQL语句的对象:Statement
5) 创建sql语句
6) 把SQL语句发送到数据库执行
7) 返回结果集对象:ResultSet
8) 遍历结果集对象,获取数据9)关闭连接,释放资源图示:
#连接数据库 import com.mysql.jdbc.Driver; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class JdbcConn { public static void main(String[] args) throws SQLException, ClassNotFoundException { //2.加载驱动程序 //mysql的驱动对象 //Driver driver = new Driver(); //DriverManager:jav提供的管理驱动的类,调用registerDriver来注册驱动程序 //问题: // 1)重复注册 //2)有硬编码 //DriverManager.registerDriver(driver); //解决问题:使用类加载的方式来加载驱动程序 Class.forName("com.mysql.jdbc.Driver"); //3.创建连接数据库的对象:Connection /* * 参数1: url : 连接到数据库的url * jdbc:mysql://IP地址:3306/数据库名?charsetEncoding=utf8 * charsetEncoding=utf8:指定连接数据库的编码格式 * 参数2:数据库用户名 * 参数3:数据库密码 * */ //java.sql包下面 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/employee5?charsetEncoding=utf8", "root","sa123"); if(conn!=null){ System.out.println("数据库连接成功!"); }else{ System.out.println("数据库连接失败!"); } } }向数据库插入数据
public void add() throws ClassNotFoundException, SQLException { //1.加载驱动程序 Class.forName("com.mysql.jdbc.Driver"); //2.获取数据库连接对象 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/employee5?charsetEncoding=utf8", "root","sa123"); //3.获取发送sql语句的对象:statement Statement stmt = conn.createStatement(); //4.创建sql语句 //注意:这里写的SQL语句跟在mysql中语法完全一样! String sql = "insert into dept values (null,'抖音部','777777')"; //5,把SQL语句发送到数据库执行 //executeUpdate: 执行增/删/改的操作 //i: 表示增/删/改影响的行数 int i = stmt.executeUpdate(sql); if(i>0){ System.out.println("成功插入["+i+"]条记录!"); }else{ System.out.println("插入失败!"); } //6.关闭连接,释放资源 stmt.close(); conn.close(); }注:增、删、改都一样,只需要修改sql语句
//向数据库修改数据 @Test public void delete() throws ClassNotFoundException, SQLException { //1.加载驱动程序 Class.forName("com.mysql.jdbc.Driver"); //2.获取数据库连接对象 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/employee5?charsetEncoding=utf8", "root","sa123"); //3.获取发送sql语句的对象:statement Statement stmt = conn.createStatement(); //4.创建sql语句 //注意:这里写的SQL语句跟在mysql中语法完全一样! String sql = " delete from dept where did=7 "; //5,把SQL语句发送到数据库执行 //executeUpdate: 执行增/删/改的操作 //i: 表示增/删/改影响的行数 int i = stmt.executeUpdate(sql); if(i>0){ System.out.println("成功删除["+i+"]条记录!"); }else{ System.out.println("删除失败!"); } //6.关闭连接,释放资源 stmt.close(); conn.close(); }2) 加载驱动程序 Class.forName(“com.mysql.jdbc.Driver”);
3) 获取数据库连接对象:Connection
4) 获取发送SQL语句的对象:Statement
5) 创建sql语句
6) 把SQL语句发送到数据库执行
7) 返回结果集对象:ResultSet
8) 遍历结果集对象,获取数据
9)关闭连接,释放资源图示:
//从数据库查询数据 //使用JDBCUtils工具类 @Test public void select2() throws ClassNotFoundException, SQLException { Connection conn = JDBCUtils.getConn(); //3.获取发送sql语句的对象:statement Statement stmt = conn.createStatement(); //4.创建sql语句 //注意:这里写的SQL语句跟在mysql中语法完全一样! String sql = " select * from dept "; //5.把SQL语句发送到数据库执行 //executeQuery:表示查询操作 //6.返回结果集对象:ResultSet //ResultSet:结果集对象 ResultSet rs = stmt.executeQuery(sql); //next():当调用next()的时候,游标会向下移动一行 //返回boolean类型,如果没有下一行了,返回false while (rs.next()){ /* * 获取数据的方式: * 1)通过 get数据类型(行下标); * 2)通过 get数据类型("列的名字"); * * * 数据库的类型 java类型 * int getInt() * char/varchar getString() * date getDate() * time getTime() * timestamp getTimestamp() * float getFloat() * double getDouble() * * */ System.out.println(rs.getInt(1)+","+ rs.getString("dname")+","+rs.getString(3)); } //7.关闭连接,释放资源 JDBCUtils.closeAll(conn,stmt,rs); }使用工具类来封装JDBC
创建类:JDBCUtils.java
封装加载驱动和获取数据库连接
1) 创建类:JDBCUtils.java 来封装
2) 使用 .properties配置文件来存放jdbc的连接信息案例演示:
db.properties
预编译对象:PreparedStatement , 继承自Statement
#配置文件,用来配置数据库连接信息 #mysql className=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/students?characterEncoding=utf8 username=root password=ROOT连接数据库的工具类
import java.io.FileReader; import java.io.IOException; import java.sql.*; import java.util.Properties; /** * @ClassName JDBCUtils * @Description TODO 连接数据库的工具类 * @Author zhaojing * @Date 2020/3/12 17:15 * @Version 1.0 */ public class JDBCUtils { //创建全局属性 private static String className; private static String url; private static String username; private static String password; static { //加载配置文件,获取连接信息 Properties pro = new Properties(); try { //写法1:读取配置文件,获取信息 //pro.load(new FileReader("db.properties")); //写法2:从当前运行的文件根目录去找文件也就是JDBCPackaging的根目录src pro.load(JDBCPackaging.class.getResourceAsStream("/db.properties")); //根据key获取value className = pro.getProperty("className"); url = pro.getProperty("url"); username = pro.getProperty("username"); password = pro.getProperty("password"); } catch (IOException e) { e.printStackTrace(); } } static { //加载驱动程序 try { Class.forName(className); } catch (ClassNotFoundException e) { e.printStackTrace(); } } //获取数据库连接对象 public static Connection getConn(){ try { return DriverManager.getConnection(url,username,password); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException("数据库连接错误!"); } } //关闭连接,释放资源 public static void closeAll(Connection conn, Statement stmt, ResultSet rs){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stmt!=null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } //方法的重载 public void closeAll(Connection conn, Statement stmt){ if(stmt!=null){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } public void closeAll(Connection conn){ if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }1.通过线程池方式建立连接
2.提取重复代码封装,子类继承封装后的父类
3.切记一定要导入相关jar包,和配置xml文件
4.命名规范实体类的名+DAO
继承了父类封装的方法
优点:
1.优化了占位符
package day14.exercise.dao; import day14.exercise.utils.ConnectionPrepared; import day14.exercise.entity.Student; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class StudentDao extends BaseDao{ /** * 实现修改属性 * @param id */ public void delete(int id){ String sql = "delete from student where stuid=?"; Object[] params = {id}; executeUpdate(sql,params); } /** * 实现增加记录 * insert into student values(null,?,?,?,?) */ public void insert(Student stu){ String sql = "insert into student values(?,?,?,?,?)"; Object[] params = {stu.getStuid(),stu.getName(),stu.getSex(),stu.getBirthday(),stu.getSclass()}; executeUpdate(sql,params); } /** *更新一条记录 */ public void update(Student stu){ String sql = "update student set name=?,sex=? where id=?"; Object[]params = {stu.getName(),stu.getSex(),stu.getStuid()}; executeUpdate(sql,params); } /** * 查询表记录 */ public List<Student>findAll(){ String sql = "select * from student"; PreparedStatement pstmt = null; ResultSet rs = null; List<Student>list = new ArrayList<>(); Student stu = null; Connection conn = null; try { conn = ConnectionPrepared.getConnection(); pstmt = conn.prepareStatement(sql); rs = pstmt.executeQuery(); while (rs.next()){ int id = rs.getInt("id"); String name = rs.getString("name"); String sex = rs.getString("sex"); String birthday = rs.getString("birthday"); String sclass = rs.getString("sclass"); stu = new Student(id,name,sex,birthday,sclass); list.add(stu); } } catch (SQLException e) { e.printStackTrace(); }finally { close(rs,pstmt,conn); } return list; } public Student findById(int id){ //1.定义sql String sql = "select * from student where id = ?"; PreparedStatement pstmt = null; ResultSet rs = null; Student stu = null; Connection conn = null; try { conn = ConnectionPrepared.getConnection(); pstmt = conn.prepareStatement(sql); pstmt.setInt(1,id); rs = pstmt.executeQuery(); if (rs.next()){//true表示有一条记录 int sid = rs.getInt("id"); String name = rs.getString("name"); String sex = rs.getString("sex"); String birthday = rs.getString("birthday"); String aClass = rs.getString("class"); stu = new Student(sid,name,sex,birthday,aClass); return stu; } }catch (Exception e){ e.printStackTrace(); }finally { close(rs,pstmt,conn); } return stu; } }jdbc java.sql.*这个包
DataSource javax.sql.* 也是一个接口,表示是一个标准是一个规范 连接池
连接池:集合,中保存了100个连接
连接Connection java程序 sql connection 数据库
连接池的实现 dbcp 连接池 c3p0 …
1.增加c3p0支持jar
2.在src中增加c3p0-config.xml文件
package com.kgc.utils; import com.mchange.v2.c3p0.ComboPooledDataSource; import javax.sql.DataSource; public class DataSourcePooled { //构造DataSource对象作为返回值对象 private static DataSource dataSource; //创建无参构造 private DataSourcePooled(){} //new ComboPooledDataSource();对象连接线程池 static { //创建一个连接池的对象,读取src下的那个连接文件 dataSource=new ComboPooledDataSource(); } public static DataSource getDataSource(){ return dataSource; } }c3p0
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <!-- 默认配置,如果没有指定则使用这个配置 --> <default-config> <property name="user">root</property> <property name="password">root</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property> <property name="driverClass">com.mysql.jdbc.Driver</property> </default-config> </c3p0-config>DBUtils组件所提供的API
query() 完成查询的方法
update() 增加删除修改的方法,
需要提供DataSource或Connection就对象
ResultSetHandler 查询的API
Serializable 8 个包装类+String 都实现了
将查询结果集中每一行映射成一个类型的对象
自动匹配【字段的值 赋给对象的属性】要求,表中字段的名称与属性名相同
new BeanHandler(Student.class) 将查询出来一条记录映射成Student类的对象 返回
new BeanListHandler<Student>(Student.class) 将查询出来一条记录映射成Student类的对象 返回 QueryRunner queryRunner=new QueryRunner(datasource); queryRunner.update(sql,objs[]) runner.update(sql,Object ... parms}); runner.query(sql,new BeanHandler<Student>(Student.class),new Object[]{1,2,3}) runner.query(sql,new BeanListHandler<Student>(Student.class),new Object[]{1,2,3}) select count(*) from student;命名规范:Dao
import java.io.Serializable; import java.util.List; public interface Dao <T>{ /** * 增加 */ public void insert(T t); /** * 删 */ public void delete(T t); /** * 改 */ public void update(T t); /** * 查 */ //public void select(Serializable serializable); List<T>findAll(); T findById(Serializable id);命名规范:实体名+Dao
import day15.entity.Student; import java.util.List; public interface StudentDao extends Dao<Student> { public Student login(String name,String pwd); /** * 用于分页查询 * @param page * @param size * @return */ List<Student>findByPage(int page,int size); }命名规范:实体名+Dao+Impl
import day15.dao.StudentDao; import day15.entity.Student; import day15.utils.DataSourcePooled; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import java.io.Serializable; import java.sql.SQLException; import java.util.List; public class StudentDaoImpl implements StudentDao { //utils提供的方法==简化了SQL查询功能 QueryRunner runner = new QueryRunner(DataSourcePooled.getDataSource()); @Override public Student login(String name, String pwd) { String sql="select * from student where name=? and pwd=?"; Student student = null; try { //通过反射得到user对象,new BeanHandler<Student>获取一个目标对象; // new BeanListHandler<Student>获取多个目标对象的集合; runner.query(sql,new BeanHandler<Student>(Student.class)); } catch (SQLException e) { e.printStackTrace(); } return student; } @Override public List<Student> findByPage(int page, int size) { String sql="select * from tbl_user where name=? and pwd=?"; List<Student> list = null; try { list = runner.query(sql,new BeanListHandler<Student>(Student.class)); } catch (SQLException e) { } return list; } @Override public void insert(Student student) { String sql = "insert into student values(null,?,?,?,?)"; int i= 0; try { i = runner.update(sql, student.getSname(), student.getSex(), student.getBirthday(), student.getS_class()); } catch (SQLException e) { e.printStackTrace(); } if (i>0) { System.out.println("成功添加了" + i + "条记录"); }else { System.out.println("添加失败!"); } } @Override public void delete(Student student) { String sql = "delete from student where stuid=?"; int i =0; try { i = runner.update(sql, student.getStuid()); } catch (SQLException e) { e.printStackTrace(); } if (i>0) { System.out.println("成功删除了" + i + "条记录"); }else { System.out.println("删除失败!"); } } @Override public void update(Student student) { String sql = "update student set sname = ? ,sex = ? ,birthday = ? , s_class = ? where stuid= ?"; int i =0; Object[] params=new Object[]{ student.getSname(), student.getSex(),student.getBirthday(),student.getS_class(),student.getStuid() }; try { i = runner.update(sql, params); } catch (SQLException e) { e.printStackTrace(); } if (i>0) { System.out.println("成功修改了" + i + "条记录"); }else { System.out.println("修改失败!"); } } @Override public List<Student> findAll() { String sql = "select * from student"; List<Student> list = null; try { list = runner.query(sql,new BeanListHandler<Student>(Student.class)); } catch (SQLException e) { e.printStackTrace(); } return list; } @Override public Student findById(Serializable id) { String sql = "select * from student"; Student student = null; try { student = runner.query(sql,new BeanHandler<Student>(Student.class)); } catch (SQLException e) { e.printStackTrace(); } return student; } }命名规范:跟表名一直,属性名也要一直
public class Student { private Integer stuid; private String sname; private String sex; private String birthday; private String s_class; public Student(Integer stuid) { this.stuid = stuid; } public Student(){ } public Student(Integer stuid, String sname, String sex, String birthday, String s_class) { this.stuid = stuid; this.sname = sname; this.sex = sex; this.birthday = birthday; this.s_class = s_class; } public Integer getStuid() { return stuid; } public void setStuid(Integer stuid) { this.stuid = stuid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getBirthday() { return birthday; } public void setBirthday(String birthday) { this.birthday = birthday; } public String getS_class() { return s_class; } public void setS_class(String s_class) { this.s_class = s_class; } @Override public String toString() { return "Student{" + "stuid=" + stuid + ", s name='" + sname + '\'' + ", sex='" + sex + '\'' + ", birthday='" + birthday + '\'' + ", s_class='" + s_class + '\'' + '}'; } }url地址语法格式
http : //ip地址 : 端口号/项目名/资源路径?参数=值
目录结构
bin : 放的是启动tomcat的程序:startup.bat shutdown.bat
conf : 放的是配置文件 : server.xml tomcat- user.xml web.xml
webapps : 放的是所有的资源文件(web项目)
work : 动态资源文件编译之后存放的位置
lib : 存放tomcat启动的jar包,和第3方jar包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ijQ0WzaU-1603283389750)(java封装源码.assets/1599229762205.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WA3CBcUQ-1603283389754)(java封装源码.assets/1599229784689.png)]
使用cmd来启动和关闭tomcat:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fblfltys-1603283389756)(java封装源码.assets/1599229804725.png)]
步骤:
1)在DOS下键入netstat -ano|findstr 8080查看占用8080端口的
配置文件都在 conf 文件夹下面 ,可以关掉相关进程
1、 修改端口号:修改server.xml
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rCQVL63s-1603283389757)(java封装源码.assets/1599229997207.png)]
1、 配置用户名和密码:修改tomcat-users.xml
<user username="zhaojing" password="123456" roles="manager-gui"/>[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iUJqi2b7-1603283389759)(java封装源码.assets/1599230111188.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ODmR6wk1-1603283389760)(java封装源码.assets/1599802369510.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tAQhUclk-1603283389760)(java封装源码.assets/1599802382104.png)]
dao文件代码
public class UserDaoImpl implements UserDao { //创建 QueryRunner对象 连接线程池 QueryRunner runner = new QueryRunner(DataSourcePooled.getDataSource()); @Override //查找的方法 public User login(String u_name, String u_pwd) { String sql = "select * from s_user where u_name =? and u_pwd = ? "; User user = null; try { user = runner.query(sql,new BeanHandler<User>(User.class),u_name,u_pwd); } catch (SQLException e) { e.printStackTrace(); } return user; } }登录页面代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>用户登录</title> </head> <body> //yanzheng.jsp 验证的jsp文件 <form method="post" action="yanzheng.jsp"> 账号:<input type="text" name="amin"/> <br/> 密码:<input type="password" name="pwd"/><br/> <input type="submit" value="提交"/> </form> </body> </html>验证jsp代码
<% User user = new User(); UserDaoImpl userDao = new UserDaoImpl(); //通过request.getParameter方法得到value的值 String amin = request.getParameter("amin"); String pwd = request.getParameter("pwd"); //如果返回的对象为空则数据库没有 if (userDao.login(amin,pwd)!=null ){ response.sendRedirect("register.jsp"); }else { //window.location.href='amids.jsp';如果密码错误回到登录页面 out.print("<script>alert('账号或密码不正确!');window.location.href='amids.jsp'; </script>"); } %>工程名 myweb
src 源码目录
web 目录 根目录 通过浏览器访问的是这个目录下的文件
WEB-INF 这个目录是web程序的私有目录,外部不能不能直接访问
web.xml web程序的描述文件 完成程序的注册
<welcome-file-list> <welcome-file>index.jsp</welcome-file> <welcome-file>hello.jsp</welcome-file> </welcome-file-list>发一个请求http://localhost:8080/index.jsp
lib目录 存放第三方jar包 c3p0 mysql…
classes目录 存放src目录下所有源码编译后的字节码文件 class文件
java server page java服务器端的页面
jsp=html+java代码 html可以使用浏览器直接打开 java 要有java运行的环境 浏览器不能直接打开jsp文件
jsp 运行环境 tomcat
1.转译 index.jsp----转译—index_jsp.java文件
2.编译 -index_jsp.java 编译成 -index_jsp.class 字节码
3.执行这个字节码全部生成html标签
4.浏览器就可以打开这个html标签
第一次通过tomcat来访问jsp,经过上面这个流程
page import taglib uri prefix include file
指令<% @ 指令名 属性="" 属性=“”%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>1) page:设置页面属性导包
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import ="com.kgc.entity.*,com.kgc.dao.*"%> <%@ page import ="com.kgc.utils.*"%>2)taglib指令 导入标签库 jstl
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>3)index.jsp index_jsp.java
index.jsp index_jsp.java <%@ include file="table.jsp"%> 静态包含 默诵与编译不生新文件,只有一个文件 index_jsp.java…未完待续
代码块 jsp中加java代码
<table width="500px" border="1px"> <tr> <th>编号</th> <th>姓名</th> <th>年龄</th> </tr> <% for(int i=10;i<100;i+=10) { %> <tr> <td>101</td><td>张三</td><td>23</td> </tr> <%} %> </table> <% Date date=new Date(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); String rq=sdf.format(date); out.print(rq); out.print("<br/>") out.prnt("<hr width=200px/>")//out.print()会内容输出在网页面上 %>表达式:计算并输出计算结果
<%=表达式 %> 在jsp的当前位置输出这个表达式的结果 name=<%=name %> 变量表达式后没有; name=<%out.print(name);%><%=变量名/10+100 %>
可通过转发功能简化打开登录界面的步骤
<%--通过jsp转发功能简化访问的步骤--%> <jsp:forward page="pages/main.jsp"></jsp:forward>Servlet的Web.xml配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <!--servlet的名字--> <servlet-name>ServletDemo</servlet-name> <!--servlet的全路径--> <servlet-class>cn.kgc.ServletDemo</servlet-class> <!--设置初始化参数--> <init-param> <param-name>code</param-name> <param-value>utf-8</param-value> </init-param> <!--servlet加载的优先级,配置之后,当tomcat一启动,就创建servlet对象==不过这个一般情况不配置!!!--> <!--里面的数字表示如果有多个配置存在的话,执行的顺序,1代表第一个,2代表第二个--> <load-on-startup>1</load-on-startup> </servlet> <!--映射配置--> <servlet-mapping> <!--servlet的名字,必须要跟servlet-name标签中的完全一致!--> <servlet-name>ServletDemo</servlet-name> <!--url的虚拟路径--> <url-pattern>/ServletDemo</url-pattern> </servlet-mapping> </web-app>1) 实现javax.servlet.Servlet接口
2) 继承javax.servlet.GenericServlet类
3) 继承javax.servlet.http.HttpServlet类 = 常用的方式
Servlet接口相关类型:
接口名作用ServletRequest表示请求对象,请求对象里面保存的就是浏览器发送的请求数据ServletResponse表示响应对象,响应对象里面保存的就是服务器返回给浏览器的响应数据ServletConfig它表示Servlet配置对象,它对应Servlet的配置信息ServletConfig对象一般用来获取项目配置的初始化信息(范围太大,需要强转,比较麻烦)
继承自GenericServlet类
ctrl+o重写doGet和doPost方法
负责对浏览器进行响应的对象
ServletResponse接口,HttpServletResponse接口继承自ServletResponse 使用的是子接口 HttpServletResponse,此接口对象由Tomcat引擎提供 可以实现对客户端的响应, 响应行,响应头,响应体
设置状态码: setStatus(int 状态码)
状态码状态404找不到资源=路径错误500程序错误302重定向200正确成功响应一般都是浏览器自动设置好的,浏览器会自动检测,设置合适的状态码
HTTP的响应体,就是页面的正文部分
1、 post请求和响应中文乱码
request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8");2、get请求和响应中文乱码怎么解决==9版本解决方式
在server.xml中加上URIEncoding=“utf-8”
<Connector port="8089" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="utf-8"/>请求头数据格式键值对, k:v 指导性信息,指导服务器
返回值类型方法作用StringgetHeader(String key)根据请求头名称,返回请求头的值EnumerationgetHeaderNames()得到所有的键(请求头),并存在一个Enumeration枚举类型里。01)数据通过request的请求参数传递到服务器。
返回值类型方法作用StringgetParameter(“表单中的name值”)获取指定的请求参数String[]getParameterValues(“表单中的name值”)获取参数中的一键多值Map<String,String[]>getParameterMap()获取提交的所有参数02)beanUtils的使用:
//populate:可以直接把map中的数据赋值给实体类的属性!!! //注意:表单中的name属性的名字必须要跟实体中的属性的名字完全一致!!! BeanUtils.populate(实体对象,map集合);03)对象里包含时间日期类型解决方法
//populate:可以直接把map中的数据赋值给实体类的属性!!! //注意:表单中的name属性的名字必须要跟实体中的属性的名字完全一致!!! UserDemo userdemo = new UserDemo(); try { //需要把String类型的日期转换成Date类型的日期 //DateConverter:日期转换器 DateConverter dateConverter = new DateConverter(); //设置转换格式 dateConverter.setPatterns(new String[]{"yyyy-MM-dd","yyyy-MM-dd HH:mm:ss"}); //实现注册转换 ConvertUtils.register(dateConverter, Date.class); BeanUtils.populate(userdemo,parameterMap); //爱好单独处理 userdemo.setChk(Arrays.toString(chks)); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } System.out.println(userdemo);作用:
1、通过一个servlet访问到另外一个servlet
2、通过一个servlet访问到一个js页面
概念:两次访问和请求:
1、页面先发送请求给A服务器,A服务器给页面响应另外一个服务器B的地址。
2、页面重新访问B服务器完成响应;
//两步合成一步: //注意:如果有项目名,那么在url中必须写项目名; response.sendRedirect("文件路径");[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gYQGA19w-1603283389762)(java封装源码.assets/1599611771595.png)]
转发的实现步骤:
1) request对象方法获取转发器 RequestDispatcher getRequestDispatcher(“转发地址”)返回值就是转发器
request.getRequestDispatcher("jsp/UpleUser.jsp").forward(request,response);2) 使用转发器对象的方法 forward
3) 转发的时候:注意:不需要再写项目名!!
1、 转发是1次请求和响应;重定向2次请求和响应。
2、 转发的URL地址不变;重定向URL地址会发生变化。
3、 转发是发生在服务器的内部;重定向返回了客户端
4、 转发的请求里面的数据一直有效;重定向的请求不会携带数据的。
5、 转发不需要再写应用的名字;重定向是需要写应用的名字。
如果你想得到request请求的数据,必须用转发; 如果我们不需要request请求的数据,用重定向。
概念:实现数据通过共享来实现数据的传递
作用域对象范围调用方式pageContext本页面jsp内置对象request一个请求中共享数据,生命周期短内置对象,可直接调用session每用户 购物车 session.invalidate(); 同一个浏览器不同窗口打开文件都可以共享,关闭浏览器销毁;需创建application每应用程序,tomcat服务器为每一个应用创建一个application对象,这个对象可以供所有用户访问jsp内置对象 //存数据 request.setAttribute(key,value) //取数据 request.getAttribute(key,value) //示例 得到一个会话对象 HttpSession session = request.getSession(); session.setAttribute("list",list); <% //application对象 //点一次页面num++; Object obj= application.getAttribute("num"); Integer num=null; if(obj==null){ application.setAttribute("num",new Integer(1)); num=1; }else{ num=(Integer)obj; num++; application.setAttribute("num",num); } %> num=21.获取当前点击用户的一个id属性值
2.通过id去数据库查找该行的所有属性值,返回一个对象集合,通过session作用域对象存入
3.从session中取出属性,显示在页面上,在提交给修改的类方法
4.返回修改结果
<html> <head> <title>Title</title> </head> <body> <h2>用户浏览信息</h2> <% //从session中取出list属性 List<User> list = (List<User>)session.getAttribute("list"); %> <table width="500px" border="1"> <tr> <th>用户</th><th>密码</th> </tr> <% if (list != null){ for (User user : list) { %> <tr> <%--<td><a href="/UpleServlet?u_name=<%=user.getU_name()%>"><%=user.getU_name()%></a></td>--%> <td><%=user.getU_name()%></td> <td><%=user.getU_pwd()%></td> //获取当前属性的name属性值 <td><a href="../../UpleServlet?u_name=<%=user.getU_name()%>">修改</a></td> </tr> <%}}%> </table> </body> </html> @WebServlet(urlPatterns = "/UpleServlet") public class UpleServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); String name = request.getParameter("u_name"); UserDaoImpl userDao = new UserDaoImpl(); User user = userDao.findById(new User(name)); request.setAttribute("user",user); System.out.println(user); request.getRequestDispatcher("jsp/UpleUser.jsp").forward(request,response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } } <html> <head> <title>修改</title> </head> <body> <% User user = (User) request.getAttribute("user"); %> <div> <h1>修改用户数据</h1> <form method="post" action="upServlet"> 更改用户名:<input type="text" name="amid" value="<%=user.getU_name()%>"/><br/> 更改用户密码:<input type="text" name="pwd" value="<%=user.getU_pwd()%>"/><br/> <input type="submit" value="确认"/> </form> </div> </body> </html> @WebServlet(urlPatterns = "/upServlet") public class upServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); String amid = request.getParameter("amid"); String pwd = request.getParameter("pwd"); UserDaoImpl userDao = new UserDaoImpl(); String user = userDao.update(new User(amid, pwd)); response.getWriter().write("<script>alert('"+user+"');window.location.href='amids.jsp'; </script>"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } }UserDaoImpl
@Override public List<User> findAll(User user) { List<User> list=null; //1.sql语句 String sql="select * from tbl_user where 1=1"; if(user.getName()!=null){//表示用户提交了一个name的查询条件 sql=sql+ " and name like '%"+user.getName()+"%'"; } if(user.getAge()!=null){ sql=sql+" and age="+user.getAge(); } try { list=runner.query(sql,new BeanListHandler<User>(User.class)); } catch (SQLException e) { e.printStackTrace(); } return list; }查询
protected void doList(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); List<User> list = null; String amd = request.getParameter("amd"); String pw = request.getParameter("pw"); // List<User> list= null; UserDao userDao=new UserDaoImpl(); //List<User> list = userDao.findAllwhere(new User(amd, pw)); //根据查询条件创建查询对象 if (amd==null && pw ==null){ list = userDao.findAll(); }else { list = userDao.findAllwhere(new User(amd,pw)); } //得到一个会话对象 HttpSession session = request.getSession(); session.setAttribute("list",list); request.getRequestDispatcher("jsp/listUser2.jsp").forward(request,response); }1.检查数据库是否开启状态
2.地址问题,注意引用路径
3.jsp表达式出错也可能导致页面不显示
保存客户端浏览器中一组小文件
Cookie 是存储在客户端计算机上的文本文件,并保留了各种跟踪信息。Java Servlet 显然支持 HTTP Cookie。
识别返回用户包括三个步骤:
服务器脚本向浏览器发送一组 Cookie。例如:姓名、年龄或识别号码等。 浏览器将这些信息存储在本地计算机上,以备将来使用。 当下一次浏览器向 Web 服务器发送任何请求时,浏览器会把这些 Cookie 信息发送到服务器,服务器将使用这些信息来识别用户。
案例:将用户提交的name与pwd保存到 cookie中
response.addCookie(cookie),将cookie的内容写以浏览器中
发请求,request对象会自动带上cookie的值
request.getCookies(); 得到这个一个服务器在这个浏览器上保存所有 cookie
mvc模式 是一种 模型
一种编程经验,解决一类问题的方法的总结;
(类似的23种设计模式)
mvc是为web程序结构定义一种模式 springmvc struts1.x struts2.x 都实现了mvc模式
M:Model 模型 dao层数据访问对象 UserDaoImpl
V: View 视图 提供用户操作的界面,提供数据输入与输出 view提供输入,输入的数据提交给Controller来处理
视图要为用户展示数据,也由Controller来提供
C:Controller 控制器 接受用户浏览器的请求,为请求产生响应 Servlet mode2 mode1
EL表达式是jsp2.0中的一个标准,它的主作用取作用域对象中的值 在jsp页面上输入或计算后再输出 4个
request sessjon applicaiton
EL中有4跟作用域有关内置对象
pageScope requestScope sessionScope applicationScope
sessionName:${sessionScope.name} 指定输入指作用域对象中的属性值调用 user对象的get方法
${user.name}${user.pwd}${user.addr} 调用 user对象的get方法 $(user.name) user.getName(); getAddr();同上,两个方法的效果一样 getName1 将get去 首字母小写name1pageContext对象
${pageContext.request.contextPath} 通过El表达得到当前应用的根目录作运算
Age=${user.age+10} ${a>b?1:2}在jsp页面通过标签形式来完成java代码的功能
jsp=html+java代码 html+jstl形式 EL集成使用
导入jstl1.2.jar
c.tld文件中c标签的描述文件,c是jstl的核心标签库
用于文件上传!
import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Map; import java.util.Random; import java.util.UUID; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; public class StringUtils { private static String[] binaryArray = {"0000","0001","0010","0011", "0100","0101","0110","0111", "1000","1001","1010","1011", "1100","1101","1110","1111"}; // private static String[] chineseDigits = new String[] { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"}; public static String[] chineseDigits = new String[] { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九"}; private static final char[] charBytes = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}; private static final char[] numberBytes = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; /** * 生成指定位数的随机数子. * @param number * @return */ public static String randomNumbers(int number) { int count = 0; //生成的密码的长度 int i; //生成的随机数 final int maxNum = numberBytes.length; StringBuffer randomStr = new StringBuffer(""); Random r = new Random(); while(count < number){ //生成随机数,取绝对值,防止生成负数, i = Math.abs(r.nextInt(maxNum)); //生成的数最大为36-1 if (i >= 0 && i < numberBytes.length) { randomStr.append(numberBytes[i]); count ++; } } return randomStr.toString(); } public static String randomStrByNumber(int number) { int count = 0; //生成的密码的长度 int i; //生成的随机数 final int maxNum = charBytes.length; StringBuffer randomStr = new StringBuffer(""); Random r = new Random(); while(count < number){ //生成随机数,取绝对值,防止生成负数, i = Math.abs(r.nextInt(maxNum)); //生成的数最大为36-1 if (i >= 0 && i < charBytes.length) { randomStr.append(charBytes[i]); count ++; } } return randomStr.toString(); } public static String randomUUID() { UUID uuid = UUID.randomUUID(); return uuid.toString().replace("-", "").toUpperCase(); } public static String digitsTochinese(int i){ //大于10的需要重写 return chineseDigits[i]; } public static String toAllUpperCase(String uuid) { StringBuffer buffer = new StringBuffer(); for (int i = 0; i < uuid.length(); i++) { char c = uuid.charAt(i); if (Character.isLowerCase(c)) { buffer.append(Character.toUpperCase(c)); } else { buffer.append(c); } } return buffer.toString(); } // 十六进制字符串转byte数组 public static byte[] hexStringToBytes(String hexString) { if (hexString == null || hexString.equals("")) { return null; } hexString = hexString.toUpperCase(); int length = hexString.length() / 2; char[] hexChars = hexString.toCharArray(); byte[] d = new byte[length]; for (int i = 0; i < length; i++) { int pos = i * 2; d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); } return d; } private static byte charToByte(char c) { return (byte) "0123456789ABCDEF".indexOf(c); } // 数组转字符串、以空格间隔 public static String bytesToHexString(byte[] src) { StringBuilder stringBuilder = new StringBuilder(""); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } if (i == src.length - 1) { stringBuilder.append(hv); } else { stringBuilder.append(hv); } } return stringBuilder.toString(); } public static String bytesToHexStringNoAppendBit(byte[] src) { StringBuilder stringBuilder = new StringBuilder(""); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v); /*if (hv.length() < 2) { stringBuilder.append(0); }*/ if (i == src.length - 1) { stringBuilder.append(hv); } else { stringBuilder.append(hv); } } return stringBuilder.toString(); } public static String bytesToString(byte[] src, String split) { StringBuilder stringBuilder = new StringBuilder(""); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = String.valueOf(v); if (i == src.length - 1) { stringBuilder.append(hv); } else { stringBuilder.append(hv + split); } } return stringBuilder.toString(); } public static String generateHexString(int paramInt) { StringBuffer localStringBuffer = new StringBuffer(); Random localRandom = new Random(); int i = 16; for (int j = 0; j < paramInt; j++) { if (j % 2 == 0) { localStringBuffer.append("0123456789ABCDEF".charAt(localRandom .nextInt(i))); } else { localStringBuffer.append("0123456789ABCDEF".charAt(localRandom .nextInt(i)) + " "); } } return localStringBuffer.toString(); } public static byte[] decodeTripleDES(byte[] data, byte[] key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { byte[] keys; if (key.length == 16) { keys = new byte[24]; System.arraycopy(key, 0, keys, 0, 16); System.arraycopy(key, 0, keys, 16, 8); } else { keys = key; } Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding"); SecretKey secretKey = new SecretKeySpec(keys, "DESede"); cipher.init(Cipher.DECRYPT_MODE, secretKey); return cipher.doFinal(data); } public static boolean equals(byte[] b1, byte[] b2) { if (b1.length != b2.length) { return false; } for (int i = 0; i < b1.length; i++) { if (b1[i] != b2[i]) { return false; } } return true; } /** * * @return 转换为二进制字符串 */ public static String bytes2BinaryStr(byte[] bArray){ String outStr = ""; int pos = 0; for(byte b:bArray){ //高四位 pos = (b&0xF0)>>4; outStr+=binaryArray[pos]; //低四位 pos=b&0x0F; outStr+=binaryArray[pos]; } return outStr; } /**将二进制转换成16进制 * @param buf * @return */ public static String binaryToHexString(byte[] bytes) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { String hex = Integer.toHexString(bytes[i] & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } sb.append(hex.toUpperCase()); } return sb.toString(); } /**将16进制转换为二进制 * @param hexStr * @return */ public static byte[] hexStringToBinary(String hexStr) { if (hexStr.length() < 1) return null; byte[] result = new byte[hexStr.length()/2]; for (int i = 0;i< hexStr.length()/2; i++) { int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16); int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16); result[i] = (byte) (high * 16 + low); } return result; } //十六进制转为字符 public static String hexStringToString(String s) { byte[] baKeyword = new byte[s.length() / 2]; for (int i = 0; i < baKeyword.length; i++) { try { baKeyword[i] = (byte) (0xff & Integer.parseInt( s.substring(i * 2, i * 2 + 2), 16)); } catch (Exception e) { e.printStackTrace(); } } try { s = new String(baKeyword, "utf-8");// UTF-16le:Not } catch (Exception e1) { e1.printStackTrace(); } return s; } /** * 给某个日期加几天后的日期 eg:2013-06-28号+1天是 2013-06-29 ,+3天是2013-07-01 * @param date 日期 * @param dump 数字 * @return */ public static String getDateByAddSomeDay(Date date,int dump){ Calendar ca=Calendar.getInstance(); SimpleDateFormat sm = new SimpleDateFormat("yyyy-MM-dd"); //构造任意格式 String today = sm.format(date); String[] timeArray= today.split("-"); ca.set(Calendar.YEAR,Integer.parseInt(timeArray[0])); ca.set(Calendar.MONTH, Integer.parseInt(timeArray[1])-1); ca.set(Calendar.DAY_OF_MONTH,Integer.parseInt(timeArray[2])); ca.add(Calendar.DAY_OF_MONTH, dump); String someDay = sm.format(ca.getTime()); return someDay; } /** * 生成公钥 * @param pubkey * @return * add by yaoyuan */ public static String generatePublicKey(String pubkey) { // BASE64Encoder base64en = new BASE64Encoder(); // String encode = base64en.encode(hexStringToBinary(pubkey)); // encode = "-----BEGIN RSA PUBLIC KEY-----" + encode + "-----END RSA PUBLIC KEY-----"; // if (encode.getBytes().length < 256) { // encode = org.apache.commons.lang.StringUtils.rightPad(encode, 256, "0"); // } // return encode; return null; } /** * 获取当前时间 精确到毫秒 */ public static String getCurrentTime(){ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); String currentTime = sdf.format(new Date()); return currentTime; } /** * @功能: BCD码转为10进制串(阿拉伯数据) * @参数: BCD码 * @结果: 10进制串 */ public static String bcd2Str(byte[] bytes) { StringBuffer temp = new StringBuffer(bytes.length * 2); for (int i = 0; i < bytes.length; i++) { temp.append((byte) ((bytes[i] & 0xf0) >>> 4)); temp.append((byte) (bytes[i] & 0x0f)); } return temp.toString().substring(0, 1).equalsIgnoreCase("0") ? temp .toString().substring(1) : temp.toString(); } /** * @功能: 10进制串转为BCD码 * @参数: 10进制串 * @结果: BCD码 */ public static byte[] str2Bcd(String asc) { int len = asc.length(); int mod = len % 2; if (mod != 0) { asc = "0" + asc; len = asc.length(); } byte abt[] = new byte[len]; if (len >= 2) { len = len / 2; } byte bbt[] = new byte[len]; abt = asc.getBytes(); int j, k; for (int p = 0; p < asc.length() / 2; p++) { if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) { j = abt[2 * p] - '0'; } else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) { j = abt[2 * p] - 'a' + 0x0a; } else { j = abt[2 * p] - 'A' + 0x0a; } if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) { k = abt[2 * p + 1] - '0'; } else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) { k = abt[2 * p + 1] - 'a' + 0x0a; } else { k = abt[2 * p + 1] - 'A' + 0x0a; } int a = (j << 4) + k; byte b = (byte) a; bbt[p] = b; } return bbt; } /** * 去除字符串中的符合${}形式的子串. * @param * @return 去除${}的字符串 */ public static String escape$String(String input) { return input.replaceAll("\\$\\{[^}]*\\}", ""); } public static String replace$String(String input, String newStr) { return input.replaceAll("\\$\\{[^}]*\\}", newStr); } public static String replace$SpecifyString(String input, String str, String newStr) { if(input != null){ input = input.replaceAll("\\$\\{" + str + "\\}", newStr); } return input; } public static String replace$String(Map<String, Object> map, String src) { if (src != null && map != null) { for (String key : map.keySet()) { String value = String.valueOf(map.get(key)); src = replace$SpecifyString(src, key, value); } } return src; } /** * 生成验证码 * @return */ public static String createValidateCode(){ String str = "0,1,2,3,4,5,6,7,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D"; String str2[] = str.split(",");//将字符串以,分割 String code=""; for(int i=0;i<4;i++){ int a=(int)(Math.random()*36); code=code+str2[a]; } return code; } /** * 根据身份证计算年龄 * @param idNumber * @return */ public static int calculateAgeByIdNumber(String idNumber){ int leh = idNumber.length(); int years =0; if (leh == 18) { years=Integer.parseInt(idNumber.substring(6, 10)); }else { years = Integer.parseInt("19" + idNumber.substring(6, 8)); } Calendar a=Calendar.getInstance(); return a.get(Calendar.YEAR)-years; } /** * 根据身份证计算性别 * @param idNumber * @return */ public static int calculateSexByIdNumber(String idNumber){ int leh = idNumber.length(); int se =0; if (leh == 18) { se=Integer.valueOf(idNumber.substring(16,17)) % 2; } return (se==1?1:2); } /** * 查找数字在数组中得区间. * @param sortedData 排序数组 * @param findValue * @return */ public static int searchValueSectionInArr(Integer[] sortedData,int findValue) { int start = 0; int end = 0; for (int i = 0; i < sortedData.length; i++) { if (findValue >= sortedData[i]) { start = i; } else { end = i; break; } } return start; } /** * 循环二分查找数组区间,返回第一次出现该值的位置 * @param sortedData 已排序的数组 * @param findValue 需要找的值 * @return 值在数组中的位置,从0开始。找不到返回-1 */ public static int binarySearch(Integer[] sortedData,int findValue) { int start=0; int end=sortedData.length-1; while(start<=end) { //中间位置 int middle=(start+end)>>1; //相当于(start+end)/2 // System.out.println("middle==>>" + middle); //中值 int middleValue=sortedData[middle]; if(findValue < middleValue) { //小于中值时在中值前面找 end = middle-1; //如果小于前边的值 和前 前边的值 则继续下一次查找 if (end >= 0) { int end_v =sortedData[end]; if (findValue >= end_v) { return end; } } else { return middle; } } else { //大于中值在中值后面找 start=middle+1; if (start <= sortedData.length -1) { int end_v = sortedData[start]; if (findValue < end_v) { return middle; } } else { return middle; } } } //找不到 return -1; } public static void main(String[] args) { /*Integer age=calculateAgeByIdNumber("133022198201242396"); Integer sex=calculateSexByIdNumber("133022198201242396"); System.out.println("age"+age+">>>>>>sex>>>>>>>>>"+sex);*/ String oldFileName="c101.jpg"; //取上传文件的扩展名 String suff=oldFileName.substring(oldFileName.lastIndexOf(".")); System.out.println(StringUtils.randomUUID()+suff); } }定义一个接口一个实现类==方法跟Controller类似,通过这一层直接访问Dao层,
Service层主要负责逻辑运算,让Controller层更简化,只负责取、调、转让代码更便于维护
代码处标记1/2/3/4
//完成文件上传 完成增加的功能 带上传 protected void doUpload(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //创建一个FileItemFactory DiskFileItemFactory factory=new DiskFileItemFactory(); //设置缓冲区 factory.setSizeThreshold(1024*100); //构造上传的组件 ServletFileUpload upload=new ServletFileUpload(factory); upload.setHeaderEncoding("utf-8"); String path=getServletContext().getRealPath("upload").toString(); File dir=new File(path); if(!dir.exists()){ dir.mkdir(); } /*1.第一处*/ String name=""; String price=""; String typeId=""; String createTime=""; String fileName=""; boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (isMultipart) { try { //解析请求,将表单中每个输入项封装成一个FileItem对象 5 List<FileItem> fileItems = upload.parseRequest(request); // 迭代表单数据 for (FileItem fileItem : fileItems) { //判断输入的类型是 普通输入项 还是文件 if (fileItem.isFormField()) { /*2.第二处*/ if("name".equals(fileItem.getFieldName())){ name=fileItem.getString("UTF-8"); } if("price".equals(fileItem.getFieldName())){ price=fileItem.getString("UTF-8"); } if("typeId".equals(fileItem.getFieldName())){ typeId=fileItem.getString("UTF-8"); } if("createTime".equals(fileItem.getFieldName())){ createTime=fileItem.getString("UTF-8"); } } else { fileName=fileItem.getName(); String ext = fileName.substring(fileName.lastIndexOf(".")); fileName = StringUtils.randomUUID()+ext; //在指的目录下构造一个空文件 File file = new File(path+"\\"+fileName); fileItem.write(file); } } } catch (FileUploadException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }else{ System.out.println("普通表单"); } //用户增加的数据存储到数据库中 /*3.第三处*/ Goods goods=new Goods(name,Integer.parseInt(price),createTime,fileName,Integer.parseInt(typeId)); /*4.第四处*/ goodsService.insertGooods(goods); response.sendRedirect("GoodsServlet"); }加上id、更改dom层方法即可
//完成修改 protected void doUpdate(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //创建一个FileItemFactory DiskFileItemFactory factory=new DiskFileItemFactory(); //设置缓冲区 factory.setSizeThreshold(1024*100); //构造上传的组件 ServletFileUpload upload=new ServletFileUpload(factory); upload.setHeaderEncoding("utf-8"); String path=getServletContext().getRealPath("upload").toString(); File dir=new File(path); if(!dir.exists()){ dir.mkdir(); } String id=""; String name=""; String price=""; String typeId=""; String createTime=""; String fileName=""; boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (isMultipart) { try { //解析请求,将表单中每个输入项封装成一个FileItem对象 5 List<FileItem> fileItems = upload.parseRequest(request); // 迭代表单数据 for (FileItem fileItem : fileItems) { //判断输入的类型是 普通输入项 还是文件 if (fileItem.isFormField()) { if("id".equals(fileItem.getFieldName())){ id=fileItem.getString("UTF-8"); } if("name".equals(fileItem.getFieldName())){ name=fileItem.getString("UTF-8"); } if("price".equals(fileItem.getFieldName())){ price=fileItem.getString("UTF-8"); } if("typeId".equals(fileItem.getFieldName())){ typeId=fileItem.getString("UTF-8"); } if("createTime".equals(fileItem.getFieldName())){ createTime=fileItem.getString("UTF-8"); } } else { fileName=fileItem.getName(); String ext = fileName.substring(fileName.lastIndexOf(".")); fileName = StringUtils.randomUUID()+ext; //在指的目录下构造一个空文件 File file = new File(path+"\\"+fileName); fileItem.write(file); } } } catch (FileUploadException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }else{ System.out.println("普通表单"); } //用户增加的数据存储到数据库中 Goods goods=new Goods(name,Integer.parseInt(price),createTime,fileName,Integer.parseInt(typeId)); goods.setId(Integer.parseInt(id)); goodsService.udpateBook(goods); response.sendRedirect("GoodsServlet"); }1.sql语句如果确定没错的话就检查一下空格,此类问题容易解决
2.单引号问题,一般不需要加单引号。如果加的话要成对加,sql语句报错的话如果报错行检查没问题,就顺延往上检查
3.选择器一定要用if-else,常量放在前面,不然重定向必须带参数,不然空指针,或者出现重复转发现象
4.文件上传如果传递值是空的话检查一下构造方法,打印出来看下有没有在赋值的过程出现错误,导致传参失败!
5.sql语句的判断每一层都要检查,分页查询的返回记录数方法跟dao层的方法判断要一致并且要经过测试排除问题
6.如果是带文件上传一定要在form表单加上传的代码,否则报错
7.报错行不一定是问题出现的行,排查问题要从实体类的构造方法→dao层→service层→servlet层→页面显示层,逐一判断
8.条件分页查询的判断要注意跟查询记录数的方法一致
任务
字符编码的转换
权限控制[没有登录不能访问[页面]
实现一个过滤器
实现一个Filter的接口
public class MyFilter implements Filter { public void destroy() { } // 过滤器链 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //保证请求经过这个过滤器后正常向下执行 chain.doFilter(req, resp); } public void init(FilterConfig config) throws ServletException { } }1.登录成功将User存放到session
2.sesion中是否有user就一个判断用户是否登录过的一个条件
3.一个资源一个组件,需要先登录才能访问
4.实现只有登录过的用户才能访问BookInfoServlet
Filter过滤重定向,转发不经过滤器
package com.kgc.filter; import com.kgc.entity.User; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; //login.jsp LoginServlet @WebFilter(urlPatterns = "/*") public class PermissionFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //当前发请求的用户是否登录过 HttpServletRequest request=(HttpServletRequest)req; HttpServletResponse response=(HttpServletResponse)resp; HttpSession session=request.getSession(); //当前用户发请求的,请求字符串 http://localhost:8080/index.jsp String uri=request.getRequestURI();///index.jsp //String url=request.getRequestURL().toString();// http://localhost:8080/index.jsp if(uri.indexOf("login.jsp")>0){ chain.doFilter(req, resp); return; } if(uri.indexOf("LoginServlet")>0){ chain.doFilter(req, resp); return; } if(request.getRequestURI().indexOf("BookInfoServlet")>0) { User user = (User) session.getAttribute("user"); if (user != null) {//当前发请求的用户登录过了 chain.doFilter(req, resp); return; } else { response.sendRedirect("login.jsp"); return; } }else{ chain.doFilter(req, resp); } } public void init(FilterConfig config) throws ServletException { } }HttpSessionListener 监听session 的创建与销毁
HttpSessionAttributeListener setAttribute(key,value)
当服务创建一个session,HttpSessionListener 就会触发一个事件sessionCreated,这个方法就被调用
服务器销毁一个session对象,HttpSessionListener中的sessionDestroyed,会被 调用
可通过a标签href调用传值事件触发js效果
html代码 <td><a href="javascript:deleteGood(${list.id})">删除</a></td> <script> function deleteGood(id) { if(confirm("是否要删除?")){ window.location.href="GoodServlet?method=doDelete&goodid="+id; } } </script>01)导入文件
<script type="text/javascript" src="js/jquery-3.2.1.js"></script>02)声明js文件或导入js文件路径
<script type="text/javascript" > $(function(){ $("td").click(function(){ alert($(this).text()); }); }); </script>03)声明jquery部分
声明==将dom对象包装成jQuery对象 $(function(){ 内容 $("td").click(function(){ alert($(this).text()); });代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>jQuery</title> <style> .c1{ color: red; font-size: 66px; } </style> </head> <body> <form action="#" method="POST"> <h1>学生系统</h1> 姓名:<input type="text" id=""> 性别:<input type="text" id=""> <hr/> <table border="1" width="800"> <tr> <th>姓名</th><th>年龄</th><th>性别</th> </tr> <tr> <td>张三</td><td>26</td><td>男</td> </tr> <tr> <td>李四</td><td>27</td><td>男</td> </tr> <tr> <td>王五</td><td>28</td><td>男</td> </tr> <tr> <td>赵六</td><td>29</td><td>男</td> </tr> </table> <img id="image1" src="img/bdlogo.gif"> </form> </body> <script type="text/javascript" src="js/jquery-3.2.1.js"></script> <script type="text/javascript" > $(function(){ $("td").click(function(){ // 获取对象的值 alert($(this).text()); // 给对象赋值 $(this).text("小李") // 给当前对象增加css属性 $(this).css("color","red") // 链式选择器==结合多种功能的语法 $(this).css("color","red").text("abc") // 语法2 $(this).css({"color":"red","font-size":"30px"}) // 在当前对象中增加class="c1" 使其对象增加c1中css样式 $("td").addClass("c1") $(this).addClass("c1") // 删除c1中属性 $(this).removeClass("c1"); // 触发事件写一个html标签 $(this).html("<h1>孙悟空</h1>"); }); // 给标签增加属性 // attr操作可使用的属性 // prop操作这个对象本身就有的属性 $("#image1").click(function(){ // 点击这个对象替换src的属性 // $(this).attr("src","img/相机.png"); $(this).prop("src","img/相机.png"); }); }); </script> </html>id选择器
语法
得到jquery类型的对象 $("#id名"); 取这个表单元素的value属性值,表单元素的值 $("#t1").val() 为表单元素赋值 $("#t1").val("新值") 非表单元素的取文本类选择器
语法同上,但获得的是一个数组
标签选择器
同类选择器
代码示例
/*输一个id 在前台显示这个用户信息*/ /*不输入,在前参显示所有信息*/ $("#all").click(function () { var userIdValue = $("#userId").val(); $.ajax({ type:"post", url:"../AjaxServlet?op=doAll", data:"userId="+userIdValue, dataType:"json", success:function (resule) { $("#ids").text(resule.userId); $("#names").text(resule.userName); $("#pwds").text(resule.userPwd); } }) });常用API
方法说明open(String method,String url,boolean async,String user ,String password)云仓配置
<mirrors> <!--复制以下代码放入mirrors中后,项目需要的jar包如果没有将会在阿里云自动下载--> <mirror> <!--This sends everything else to /public --> <id>nexus</id> <mirrorOf>*</mirrorOf> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> </mirror> <mirror> <id>nexus-public-snapshots</id> <mirrorOf>public-snapshots</mirrorOf> <url>http://maven.aliyun.com/nexus/content/repositories/snapshots/</url> </mirror> <mirror> <id>Central</id> <url>http://repo1.maven.org/maven2</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors>th>
```云仓配置
<mirrors> <!--复制以下代码放入mirrors中后,项目需要的jar包如果没有将会在阿里云自动下载--> <mirror> <!--This sends everything else to /public --> <id>nexus</id> <mirrorOf>*</mirrorOf> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> </mirror> <mirror> <id>nexus-public-snapshots</id> <mirrorOf>public-snapshots</mirrorOf> <url>http://maven.aliyun.com/nexus/content/repositories/snapshots/</url> </mirror> <mirror> <id>Central</id> <url>http://repo1.maven.org/maven2</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors>maven用骨架创建web.xml文件需要改