1、方式一:Java Enterprise
选择Java Enterprise,Java Enterprise 主要是针对Java EE 项目的开发设计的“帮助我们开发和部署可移植、健壮、可伸缩且安全的服务器端 Java应用程序”,
webapp下各package作用
pages:主要存放网页
static:存放一些静态资源,例如css,img,jquery等
// 验证用户名:必须由字母,数字下划线组成,并且长度为5到12位
//1 获取用户名输入框里的内容
var usernameText = $("#r_user_name").val();
//2 创建正则表达式对象
var usernamePatt = /^\w{
5,12}$/;
//3 使用test方法验证
if (!usernamePatt.test(usernameText)) {
//4 提示用户结果
$("span.errorMsg").text("用户名不合法!");
// alert("用户名不合法!");
$("#login_form").removeClass('shake_effect');
//setTimeout( )是设定一个指定等候时间 (单位是千分之一秒, millisecond), 时间到了, 浏览器就会执行一个指定的 method 或 function, 有以下语法:
setTimeout(function() {
$("#login_form").addClass('shake_effect')
},1);
return false;
}
// 验证密码:必须由字母,数字下划线组成,并且长度为5到12位
//1 获取用户名输入框里的内容
var passwordText = $("#r_password").val();
//2 创建正则表达式对象
var passwordPatt = /^\w{
5,12}$/;
//3 使用test方法验证
if (!passwordPatt.test(passwordText)) {
//4 提示用户结果
$("span.errorMsg").text("密码不合法!");
$("#login_form").removeClass('shake_effect');
//setTimeout( )是设定一个指定等候时间 (单位是千分之一秒, millisecond), 时间到了, 浏览器就会执行一个指定的 method 或 function, 有以下语法:
setTimeout(function() {
$("#login_form").addClass('shake_effect')
},1);
return false;
}
// 验证确认密码:和密码相同
//1 获取确认密码内容
var repwdText = $("#repwd").val();
//2 和密码相比较
if (repwdText != passwordText) {
//3 提示用户
$("span.errorMsg").text("确认密码和密码不一致!");
$("#login_form").removeClass('shake_effect');
//setTimeout( )是设定一个指定等候时间 (单位是千分之一秒, millisecond), 时间到了, 浏览器就会执行一个指定的 method 或 function, 有以下语法:
setTimeout(function() {
$("#login_form").addClass('shake_effect')
},1);
return false;
}
// 邮箱验证:[email protected]
//1 获取邮箱里的内容
var emailText = $("#r_emial").val();
//2 创建正则表达式对象
var emailPatt = /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{
1,2}[a-z]+)+$/;
//3 使用test方法验证是否合法
if (!emailPatt.test(emailText)) {
//4 提示用户
$("span.errorMsg").text("邮箱格式不合法!");
$("#login_form").removeClass('shake_effect');
//setTimeout( )是设定一个指定等候时间 (单位是千分之一秒, millisecond), 时间到了, 浏览器就会执行一个指定的 method 或 function, 有以下语法:
setTimeout(function() {
$("#login_form").addClass('shake_effect')
},1);
return false;
}
JavaBean表设计原则
1.整个表可以看做是一个类
2.表中的一行记录,对应一个类的实例(对象)
3.表中的一列,对应类中的一个成员属性
/**
* @program: JavaWebExer
* @description: Druid(德鲁伊)数据库连接池管理
* @author: 许宝华
* @create: 2021-04-03 14:32
*/
public class JDBCUtils {
//声明成员变量,数据库连接池提供一个就足够了
private static DruidDataSource dataSource;
//初始化数据路连接池对象
static{
try {
//创建配置文件对象
Properties properties=new Properties();
//Druid连接池不能加载文件主动加载配置文件 需要指定文件
//读取jdbc.properties属性配置文件
InputStream inputStream = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
//从流中加载数据
//导入配置文件
properties.load(inputStream);
//创建数据库连接池
//通过工厂类获取连接池的对象
dataSource= (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*获取数据库连接池中的连接
* @return 如果返回null,说明获取连接失败
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/3 14:34
*/
public static Connection getConnection(){
Connection conn=null;
try {
conn=dataSource.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
/**
*关闭连接,放回数据库连接池
* @param conn
* @return void
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/3 14:36
*/
public static void close(Connection conn){
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
/**
* @program: JavaWebExer
* @description: 父类代码,子类继承他的方法得以应用,封装了对数据库的通用操作
* @author: 许宝华
* @create: 2021-04-03 15:54
*/
public abstract class BaseDao {
//使用DbUtils操作数据库
private QueryRunner queryRunner=new QueryRunner();
/**
*update()方法用来执行:Insert\Update\Delete语句
* @return 如果但会-1,说明执行失败,其他返回其他表示影响的行数
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/3 16:03
*/
public int update(String sql,Object...args){
//考虑到数据库事务,使用同一个连接
Connection connection = JDBCUtils.getConnection();
try {
return queryRunner.update(connection,sql,args);
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.close(connection);
}
return -1;
}
/**
*通用的查询(任意表)返回一个JavaBean(User)的sql语句
* @param type 返回的对象类型
* @param sql 对应的sql语句
* @param args sql对应的参数值
* @return T 返回的类型的泛型
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/3 16:14
*/
public <T> T queryForOne(Class<T> type,String sql,Object...args){
Connection connection = JDBCUtils.getConnection();
try {
//为解决事务,需要使用同一个连接
//结果集new BeanHandler(type),用于封装表中的一条记录
//new BeanListHandler(type) ,用于封装表中的多条记录
//new ScalarHandler(),执行返回一行一列的sql语句,
return queryRunner.query(connection,sql,new BeanHandler<T>(type),args);
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.close(connection);
}
return null;
}
/**
*查询返回多个JavaBean(User)的sql语句
* @param type
* @param sql
* @param args
* @return java.util.List
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/3 16:21
*/
public <T>List<T> queryForList(Class<T> type,String sql,Object...args){
Connection connection = JDBCUtils.getConnection();
try {
return queryRunner.query(connection,sql,new BeanListHandler<T>(type),args);
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.close(connection);
}
return null;
}
/**
*执行返回一行一列的sql语句,例如 select COUNT(*) from 表
* @param sql 执行的sql语句
* @param args sql对应的参数值
* @return java.lang.Object
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/3 16:25
*/
public Object queryForSingleValue(String sql,Object...args){
Connection connection = JDBCUtils.getConnection();
try {
return queryRunner.query(connection,sql,new ScalarHandler(),args);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.close(connection);
}
return null;
}
}
/**
* @program: JavaWebExer
* @description: 此接口用于规范针对于user表的常用操作
* @author: 许宝华
* @create: 2021-04-03 16:28
*/
public interface UserDao {
/**
*根据用户名查询用户信息
* @param username 用户名
* @return com.xbh.Book.pojo.User 如果返回null,说明没有这个用户,
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/3 16:31
*/
public User queryUserByUsername(String username);
/**
* 保存用户信息,添加到数据库
* @param user
* @return int
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/3 16:33
*/
public int saveUser(User user);
/**
*根据用户名和密码查询用户信息
* @param username
* @param password
* @return com.xbh.Book.pojo.User 如果返回null,说明没有这个用户
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/3 16:35
*/
public User queryUserByUsernameAndPassword(String username,String password);
}
- public class UserDaoImpl extends BaseDao implements UserDao {
@Override
public User queryUserByUsername(String username) {
String sql="select id,username,PASSWORD,email from t_user where username= ?";
// String sql="SELECT id,username,PASSWORD,email FROM t_user WHERE username=\"admin\"";
return queryForOne(User.class,sql,username);
}
@Override
public int saveUser(User user) {
String sql="insert into t_user(username,PASSWORD,email) VALUES(?,?,?)";
return update(sql,user.getUsername(),user.getPassword(),user.getEmail());
}
@Override
public User queryUserByUsernameAndPassword(String username, String password) {
String sql="select id,username,password,email from t_user where username=? and password=?";
return queryForOne(User.class,sql,username,password);
}
}
public class UserDaoTest {
@Test
public void queryUserByUsername() {
UserDao userDao=new UserDaoImpl();
System.out.println(userDao.queryUserByUsername("admin"));
}
@Test
public void saveUser() {
UserDao userDao=new UserDaoImpl();
System.out.println(userDao.saveUser(new User(null,"aaa","123456789","[email protected]")));
}
@Test
public void queryUserByUsernameAndPassword() {
}
}
业务逻辑层的主要作用
1、处理业务逻辑
2、调用持久层保存到数据库
3、实现解耦操作
5.1创建接口,明确需要处理什么业务
public interface UserService {
/**
*注册用户
* @param user
* @return void
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/13 9:17
*/
public void registUser(User user);
/**
*登录
* @param user
* @return void
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/13 9:17
*/
public User login(User user);
/**
*检查用户名是否可用
* @param username
* @return 返回true表明用户名已经存在
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/13 9:17
*/
public boolean existsUsername(String username);
}
public class UserServiceImpl implements UserService {
private UserDao userDao=new UserDaoImpl();
@Override
public void registUser(User user) {
userDao.saveUser(user);
}
@Override
public User login(User user) {
return userDao.queryUserByUsernameAndPassword(user.getUsername(),user.getPassword());
}
@Override
public boolean existsUsername(String username) {
if(userDao.queryUserByUsername(username)==null){
//等于null,说明没查到,没查到表示可用
return false;
}else{
return true;
}
}
}
public class UserServiceTest {
UserService userService=new UserServiceImpl();
@Test
public void registUser() {
userService.registUser(new User(null,"bbj456","666666","[email protected]"));
}
@Test
public void login() {
System.out.println(userService.login(new User(null,"admin","admin",null)));
}
@Test
public void existsUsername() {
if(userService.existsUsername("admin4")){
System.out.println("存在");
}
}
}
http://blog.csdn.net/meiyalei/article/details/2129120
原文出处:
一、调用方式
我们知道,在servlet中调用转发、重定向的语句如下:
request.getRequestDispatcher(“new.jsp”).forward(request,
response);//转发到new.jsp response.sendRedirect(“new.jsp”);//重定向到new.jsp在jsp页面中你也会看到通过下面的方式实现转发:
当然也可以在jsp页面中实现重定向: <%response.sendRedirect(“new.jsp”);//重定向到new.jsp%>
二、本质区别
解释一一句话,转发是服务器行为,重定向是客户端行为。为什么这样说呢,这就要看两个动作的工作流程:
转发过程:
客户浏览器发送http请求----》web服务器接受此请求–》调用内部的一个方法在容器内部完成请求处理和转发动作----》将目标资源发送给客户;在这里,转发的路径必须是同一个web容器下的url,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。在客户浏览器路径栏显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。转发行为是浏览器只做了一次访问请求。重定向过程:
客户浏览器发送http请求----》web服务器接受后发送302状态码响应及对应新的location给客户浏览器–》客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址----》服务器根据此请求寻找资源并发送给客户。在这里location可以重定向到任意URL,既然是浏览器重新发出了请求,则就没有什么request传递的概念了。在客户浏览器路径栏显示的是其重定向的路径,客户可以观察到地址的变化的。重定向行为是浏览器做了至少两次的访问请求的。解释二
重定向,其实是两次request, 第一次,客户端request
A,服务器响应,并response回来,告诉浏览器,你应该去B。这个时候IE可以看到地址变了,而且历史的回退按钮也亮了。重定向可以访问自己web应用以外的资源。在重定向的过程中,传输的信息会被丢失。例子:
请求转发是服务器内部把对一个request/response的处理权,移交给另外一个
对于客户端而言,它只知道自己最早请求的那个A,而不知道中间的B,甚至C、D。 传输的信息不会丢失。例子:
解释三 假设你去办理某个执照,
重定向:你先去了A局,A局的人说:“这个事情不归我们管,去B局”,然后,你就从A退了出来,自己乘车去了B局。
转发:你先去了A局,A局看了以后,知道这个事情其实应该B局来管,但是他没有把你退回来,而是让你坐一会儿,自己到后面办公室联系了B的人,让他们办好后,送了过来。
public class RegistServlet extends HttpServlet {
private UserService userService=new UserServiceImpl();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
String code = req.getParameter("code");
//检查验证码是否正确
//忽略大小写
if("abcde".equalsIgnoreCase(code)){
//正确
if(userService.existsUsername(username)){
//不可用
System.out.println("用户名"+username+"不可用或已存在");
req.getRequestDispatcher("/pages/user/regist.jsp").forward(req,resp);
}else{
//可用
userService.registUser(new User(null,username,password,email));
//跳转到注册成功的页面
req.getRequestDispatcher("/pages/user/regist_success.jsp").forward(req,resp);
}
//
}else{
//不正确,调回注册页面
//请求转发,回到注册页面
System.out.println("验证码错误"+code);
req.getRequestDispatcher("/pages/user/regist.jsp").forward(req,resp);
}
}
}
-
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<welcome-file-list>
<welcome-file>index.jspwelcome-file>
<welcome-file>index1.jspwelcome-file>
welcome-file-list>
<servlet>
<servlet-name>RegistServletservlet-name>
<servlet-class>com.xbh.Book.web.RegistServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>RegistServletservlet-name>
<url-pattern>/registServleturl-pattern>
servlet-mapping>
<servlet>
<servlet-name>ServletDemoservlet-name>
<servlet-class>lm.practice.ServletDemoservlet-class>
servlet>
<servlet-mapping>
<servlet-name>ServletDemoservlet-name>
<url-pattern>/servleturl-pattern>
servlet-mapping>
- 在进行项目开发时,有时候用户的一个操作就会新增一个Servlet来处理相应的操作,造成Servlet的冗余现象 *
为了解决Servlet太多的造成冗余的现象,我们只需定义一个BaseServlet来获取用户想要调用的方法名, *
通过方法的名称反射来调用该类的其他方法。这样原来定义的很多个Servlet就不再需要了。
String action = req.getParameter("action");
if("login".equals(action)){
login(req,resp);
}else if("regist".equals(action)){
regist(req,resp);
}
1、 这做法虽然不再需要创建过多的Servlet,但效率低,每增加一个方法就需要修改代码,增加if判断,无疑这样做会造成代码耦合性高,不利于开发。
2、对于上面这两种问题,可以创建一个BaseServlet来解决,那就是在BaseServlet里面,继承HttpServlet。
3、通过反射来调用当前类中已有的方法,在后面的开发中,创建的Servlet(其实是类),只需要继承这个BaseServlet即可,而继承了BaseServlet的子类不管增加方法,还是删除方法,BaseServlet都不需要修改源代码,这样就可以大大减少代码量,简化了操作。
public abstract class BaseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("action");
try {
//获取action业务鉴别字符串,获取相应的业务,方法反射对象
Method declaredMethod = this.getClass().getDeclaredMethod(action,HttpServletRequest.class,HttpServletResponse.class);
//调用目标业务方法
declaredMethod.invoke(this,req,resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
-2、编写WebUtils工具类
1、WebUtils工具类的出现原因
某个业务框中存在很多用户输入的数据内容,此时我们就一条一条的获取并注入JavaBean对象中,使用大量的set方法,这太过于麻烦,于是BeanUtils诞生了。
1、BeanUtils工具类是简化数据封装JavaBean的工具类,在实际开发中可以省区很多的setXxx()的重复操作。
2、 和JDBC中的 BeanPropertyRowMapper的操作类似,BeanPropertyRowMapper是从数据库中获取的数据封装成JavaBean类型的简化操作,而BeanUtils是对从客户端获取的数据封装成javaBean类型的简化操作
3、使用BeanUtils工具类的格式如下,记得抛异常4、BeanUtils工具类接收的第一个对象是JavaBean封装类的对象,第二个参数是map集合的键值对信息(要用req.getParameterMap()的方式获取参数)
public class WebUtils {
/**
* BeanUtils.populate
*其需要给定待注入的JavaBean对象,以及对应的properties(键值对参数)。该方法利用反射调用了对应javaBean中的setxxx()方法,
* 因此一定要保证传递进入的paraName和javaBean中的属性值相同,这样才能成功调用setxxx()方法。
* 因此,在同时考虑泛型的情况下在该自定义的工具类中要从UserServlet中传递的参数应当为(Map value, T bean),
* 而不是(HttpServletRequest req, Object bean)。
*
* 这么做的原因:将Map的值注入JavaBean的需求很常见,不只有Web层有这种需求,DAO层,Service层,Web层都可能会有这种需求,
* 如果这里写成了(HttpServletRequest req, Object bean),DAO层和Service层就无法使用该方法,
* 如果写成前者的话,三层都可以使用。使用后者就会使得代码的耦合度过高——优雅。
public static T copyParamToBean(Map value, T bean){
try {
System.out.println("注入之前"+bean);
/**
* 把所有请求的参数都注入到bean对象中,注入核心是通过bean对象的set方法进行注入的
*/
BeanUtils.populate(bean,value);
System.out.println("注入之后"+bean);
} catch (Exception e) {
e.printStackTrace();
}
return bean;
}
/**
* 将字符串类型转换成为int类型
* @param strInt
* @param defaultValue 默认值
* @return void
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/22 10:07
*/
public static int parseInt(String strInt,int defaultValue){
try {
return Integer.parseInt(strInt);
} catch (Exception e) {
e.printStackTrace();
}
return defaultValue;
}
}
public class UserServlet extends BaseServlet {
private UserService userService=new UserServiceImpl();
/**
*
* @param req
* @param resp
* @return 登录
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/22 11:04
*/
protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
//检查用户名是否可用
if(userService.existsUsername(username)){
//可用
User loginUser = userService.login(new User(null, username, password, null));
//请求转发,跳转到登录成功的页面
if (loginUser==null) {
//把错误的信息和回显的表单项信息,保存到request域中
req.setAttribute("msg","用户或密码错误");
req.setAttribute("username",username);
//登录失败,返回登录页面
req.getRequestDispatcher("/pages/user/login.jsp").forward(req,resp);
} else {
//登录成功
req.getRequestDispatcher("/pages/user/login_success.jsp").forward(req,resp);
}
}else{
//不可用
System.out.println("用户名不可用,请注册,跳转回登录页面");
req.getRequestDispatcher("/pages/user/login.jsp").forward(req,resp);
}
}
/**
*
* @param req
* @param resp
* @return 注册
* @author 许宝华
* @creed: Talk is cheap,show me the code
* @date 2021/4/22 11:04
*/
protected void regist(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
String code = req.getParameter("code");
User user=WebUtils.copyParamToBean(req.getParameterMap(),new User());
//检查验证码是否正确
//忽略大小写
if("abcde".equalsIgnoreCase(code)){
//正确
if(userService.existsUsername(username)){
//不可用
req.setAttribute("msg","用户名已存在");
req.setAttribute("username",username);
req.setAttribute("email",email);
System.out.println("用户名"+username+"不可用或已存在");
req.getRequestDispatcher("/pages/user/regist.jsp").forward(req,resp);
}else{
//可用
userService.registUser(new User(null,username,password,email));
//跳转到注册成功的页面
req.getRequestDispatcher("/pages/user/regist_success.jsp").forward(req,resp);
}
//
}else{
//不正确,调回注册页面
//请求转发,回到注册页面
req.setAttribute("msg","验证码错误");
req.setAttribute("username",username);
req.setAttribute("email",email);
System.out.println("验证码错误"+code);
req.getRequestDispatcher("/pages/user/regist.jsp").forward(req,resp);
}
}
注意事项:以上仅代表自己的笔记,笔记中参考了大量前辈的经验及代码,只能说一句开源万岁,开源牛啤,此篇文章不具有任何商用价值