尚硅谷2022 javaweb网上书城

想培训和学习的多多关注尚硅谷
尚硅谷官网
尚硅谷2022 javaweb网上书城视频
文档连接
代码地址-请看book-dev分支

环境准备

安装jdk1.8

安装idea

下载tomcat

登陆设置

添加【-parameters】参数

java8新增了一个编译参数-parameters,可以让我们在运行期获取方法参数名称,没有配置获取的是arg0、arg1等,配置后获取正确的方法名和参数

否则controller传值异常

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RE0oDriq-1654307516185)(image/image-20220603094448871.png)]

添加tomcat服务

选择local

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aeei8cW2-1654307516196)(image/image-20220603094720211.png)]

导入本地Tomcat8

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8xXJRO1I-1654307516200)(image/image-20220603095020572.png)]

部署和登录

部署项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s1WZN1i1-1654307516205)(image/image-20220603095351130.png)]

登录

登录地址 : 主机:端口/page.do?operate=page&page=user/login

http://localhost:8080/page.do?operate=page&page=user/login

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KrMTxNWX-1654307516206)(image/image-20220603105034944.png)]

网上书城项目


注册请求过程

  1. 调用com.atguigu.myssm.myspringmvc.DispatcherServlet#service找到控制器
  2. 通过控制器com.atguigu.book.controller.UserController#regist找到service
  3. 通过service com.atguigu.book.service.impl.UserServiceImpl#regist找到dao
  4. com.atguigu.book.dao.impl.UserDAOImpl#addUser

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F9shDnLC-1654307516211)(image/image-20220604091040844.png)]

vue在项目中的使用

导入如下js文件

<script language="JavaScript" th:src="@{/static/script/vue.js}"></script>
<script language="JavaScript" th:src="@{/static/script/axios.min.js}"></script>

js中使用vue

window.onload=function(){
    var vue = new Vue({
        el:"#cart_div",
        data:{
            cart:{}
        },
        methods:{
            getCart:function(){
                axios({
                    method:"POST",
                    url:"cart.do",
                    params:{
                        operate:'cartInfo'
                    }
                })
                    .then(function (value) {
                        var cart = value.data ;
                        vue.cart = cart ;
                    })
                    .catch(function (reason) {  });
            },
            editCart:function(cartItemId , buyCount){
                axios({
                    method:"POST",
                    url:"cart.do",
                    params:{
                        operate:'editCart',
                        cartItemId:cartItemId,
                        buyCount:buyCount
                    }
                })
                    .then(function (value) {
                        vue.getCart();
                    })
                    .catch(function (reason) {  });
            }
        },
        mounted:function(){
            debugger;
            this.getCart() ;
        }
    });

}

页面访问和thymeleaf的使用

thymeleaf的使用

https://blog.csdn.net/ityouknow/article/details/52441288

访问index.html页面

访问WEB-INF/pages/index.html,去掉前缀“WEB-INF/pages/”,后缀.html,后台调整加上page.do,

DispatcherServlet#service作用
// 第一步 page.do -> PageController 或者 page ->PageController
// 第二步 operate=page:表示页面跳转, return Page; page=index,返回index

http://localhost:8080/page.do?operate=page&page=index
  1. WEB—INF下页面都是受保护的,需要通过后台跳转

    1、PageController.java
    public class PageController {
        public String page(String page){
            return page;      // frames/left
        }
    }
    
    2、applicationContext.xml
    <bean id="page" class="com.atguigu.myssm.myspringmvc.PageController"/>
    
    3、web.xml
        <context-param>
            <param-name>view-prefix</param-name>
            <param-value>/WEB-INF/pages/</param-value>
        </context-param>
        <context-param>
            <param-name>view-suffix</param-name>
            <param-value>.html</param-value>
        </context-param>
    

设计框架mvc和三层架构

参考博客

https://blog.csdn.net/QBDBK/article/details/121020659

mvc

  • C : controller 控制层
  • V:视图成(html,jsp,vue)
  • M:模型层(分两种:第一种service,dao业务模型,第二种entity实体类模型)

第一种:
有现成前端页面(类似或者可以借鉴的)
创建项目,导包或配置maven,基本框架搭建的工作准备(实体,工具类,配置文件)
V:前端视图
C:servlet
M:service(serviceimp)
M:dao(daoimp)
M:entity

第二种:
没有可借鉴的页面
创建项目,导包或配置maven,基本框架搭建的工作准备(实体,工具类,配置文件)
C:servlet
M:service(serviceimp)
M:dao(daoimp)
M:entity
V:前端视图

实现步骤

注册功能实现

参数验证

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4xtW0fw9-1654307516213)(image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzU2NTIyNTc0,size_16,color_FFFFFF,t_70-16542202621096.png)]

验证用户名是否合法:5-12位,由数字,字母或下划线组成

验证密码是否合法:5-12位,由数字,字母或下划线组成

验证确认密码密码是否相同

验证电子邮件是否合法:

验证验证码是否非空:该阶段暂不用实现验证码的正确性判断

//用户名不能为空,而且是6~16位数字和字母组成
    var unameReg = /[0-9a-zA-Z]{6,16}/;
    var unameTxt = $("unameTxt");
    var uname = unameTxt.value ;
    var unameSpan = $("unameSpan");
    if(!unameReg.test(uname)){
        unameSpan.style.visibility="visible";
        return false ;
    }else{
        unameSpan.style.visibility="hidden";
    }

    //密码的长度至少为8位
    var pwdTxt = $("pwdTxt");
    var pwd = pwdTxt.value ;
    var pwdReg = /[\w]{8,}/; // /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,}$/;
    var pwdSpan = $("pwdSpan");
    if(!pwdReg.test(pwd)){
        pwdSpan.style.visibility="visible";
        return false ;
    }else{
        pwdSpan.style.visibility="hidden";
    }

    //密码两次输入不一致
    var pwd2 = $("pwdTxt2").value ;
    var pwdSpan2 = $("pwdSpan2") ;
    if(pwd2!=pwd){
        pwdSpan2.style.visibility="visible";
        return false ;
    }else{
        pwdSpan2.style.visibility="hidden";
    }

    //请输入正确的邮箱格式
    var email = $("emailTxt").value ;
    var emailSpan = $("emailSpan");
    var emailReg = /^[a-zA-Z0-9_\.-]+@([a-zA-Z0-9-]+[\.]{1})+[a-zA-Z]+$/;
    if(!emailReg.test(email)){
        emailSpan.style.visibility="visible";
        return false ;
    }else{
        emailSpan.style.visibility="hidden";
    }
编写数据库表中对应的javaBean对象——User类
public class User {
    private Integer id ;
    private String uname ;
    private String pwd ;
    private String email;
    private Integer role = 0 ;

    private Cart cart ;
    private List<OrderBean> orderList ; 
    // -- 省略set/get
编写工具类ConnUtil.java

ConnUtil.java

public class ConnUtil {

    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
    //private static ThreadLocal<Object> threadLocal2 = new ThreadLocal<>();
    //private static ThreadLocal<Object> threadLocal3 = new ThreadLocal<>();

    public static final String DRIVER = "com.mysql.jdbc.Driver" ;
    public static final String URL = "jdbc:mysql://localhost:3306/bookdb?useUnicode=true&characterEncoding=utf-8&useSSL=false";
    public static final String USER = "root";
    public static final String PWD = "root" ;

    private static Connection createConn(){
        try {
            //1.加载驱动
            Class.forName(DRIVER);
            //2.通过驱动管理器获取连接对象
            return DriverManager.getConnection(URL, USER, PWD);
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return null ;
    }

    public static Connection getConn(){
        Connection conn = threadLocal.get();
        if(conn==null){
            conn =createConn();
            threadLocal.set(conn);
        }
        return threadLocal.get() ;
    }

    public static void closeConn() throws SQLException {
        Connection conn = threadLocal.get();
        if(conn==null){
            return ;
        }
        if(!conn.isClosed()){
            conn.close();
            //threadLocal.set(null);
            threadLocal.remove();
        }
    }
}
编写 BaseDao和与负责数据库交互的Dao

BaseDao类

package com.atguigu.myssm.basedao;

import java.lang.reflect.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public abstract class BaseDAO<T> {
    protected Connection conn ;
    protected PreparedStatement psmt ;
    protected ResultSet rs ;

    //T的Class对象
    private Class entityClass ;

    public BaseDAO() {
        //getClass() 获取Class对象,当前我们执行的是new FruitDAOImpl() , 创建的是FruitDAOImpl的实例
        //那么子类构造方法内部首先会调用父类(BaseDAO)的无参构造方法
        //因此此处的getClass()会被执行,但是getClass获取的是FruitDAOImpl的Class
        //所以getGenericSuperclass()获取到的是BaseDAO的Class
        Type genericType = getClass().getGenericSuperclass();
        //ParameterizedType 参数化类型
        Type[] actualTypeArguments = ((ParameterizedType) genericType).getActualTypeArguments();
        //获取到的<T>中的T的真实的类型
        Type actualType = actualTypeArguments[0];

        try {
            entityClass = Class.forName(actualType.getTypeName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            throw new DAOException("BaseDAO 构造方法出错了,可能的原因是没有指定<>中的类型");
        }

    }

    protected Connection getConn(){
        return ConnUtil.getConn();
    }

    protected void close(ResultSet rs , PreparedStatement psmt , Connection conn){

    }

    //给预处理命令对象设置参数
    private void setParams(PreparedStatement psmt , Object... params) throws SQLException {
        if(params!=null && params.length>0){
            for (int i = 0; i < params.length; i++) {
                psmt.setObject(i+1,params[i]);
            }
        }
    }

    //执行更新,返回影响行数
    protected int executeUpdate(String sql , Object... params) {
        boolean insertFlag = false ;
        insertFlag = sql.trim().toUpperCase().startsWith("INSERT");

        conn = getConn();
        try{
            if(insertFlag){
                psmt = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
            }else {
                psmt = conn.prepareStatement(sql);
            }
            setParams(psmt,params);
            int count = psmt.executeUpdate() ;

            if(insertFlag){
                rs = psmt.getGeneratedKeys();
                if(rs.next()){
                    return ((Long)rs.getLong(1)).intValue();
                }
            }
            return 0 ;
        }catch (SQLException e){
            e.printStackTrace();
            throw new DAOException("BaseDAO executeUpdate出错了");
        }
    }

    //通过反射技术给obj对象的property属性赋propertyValue值
    private void setValue(Object obj ,  String property , Object propertyValue) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException {
        Class clazz = obj.getClass();

        //获取property这个字符串对应的属性名 , 比如 "fid"  去找 obj对象中的 fid 属性
        Field field = clazz.getDeclaredField(property);
        if(field!=null){

            //获取当前字段的类型名称
            String typeName = field.getType().getName();
            //判断如果是自定义类型,则需要调用这个自定义类的带一个参数的构造方法,创建出这个自定义的实例对象,然后将实例对象赋值给这个属性

            if(isMyType(typeName)){
                //假设typeName是"com.atguigu.qqzone.pojo.UserBasic"
                Class typeNameClass = Class.forName(typeName);
                Constructor constructor = typeNameClass.getDeclaredConstructor(Integer.class);
                propertyValue = constructor.newInstance(propertyValue);
            }
            field.setAccessible(true);
            field.set(obj,propertyValue);
        }
    }

    private static boolean isNotMyType(String typeName){
        return "java.lang.Integer".equals(typeName)
                || "java.lang.String".equals(typeName)
                || "java.util.Date".equals(typeName)
                || "java.lang.Double".equals(typeName)
                || "java.sql.Date".equals(typeName);
    }

    private static boolean isMyType(String typeName){
        return !isNotMyType(typeName);
    }

    //执行复杂查询,返回例如统计结果
    protected Object[] executeComplexQuery(String sql , Object... params){
        conn = getConn() ;
        try{
            psmt = conn.prepareStatement(sql);
            setParams(psmt,params);
            rs = psmt.executeQuery();

            //通过rs可以获取结果集的元数据
            //元数据:描述结果集数据的数据 , 简单讲,就是这个结果集有哪些列,什么类型等等

            ResultSetMetaData rsmd = rs.getMetaData();
            //获取结果集的列数
            int columnCount = rsmd.getColumnCount();
            Object[] columnValueArr = new Object[columnCount];
            //6.解析rs
            if(rs.next()){
                for(int i = 0 ; i<columnCount;i++){
                    Object columnValue = rs.getObject(i+1);     //33    苹果      5
                    columnValueArr[i]=columnValue;
                }
                return columnValueArr ;
            }
        }catch(SQLException e){
            e.printStackTrace();
            throw new DAOException("BaseDAO executeComplexQuery出错了");
        }

        return null ;
    }

    //执行查询,返回单个实体对象
    protected T load(String sql , Object... params){
        conn = getConn() ;
        try{
            psmt = conn.prepareStatement(sql);
            setParams(psmt,params);
            rs = psmt.executeQuery();

            //通过rs可以获取结果集的元数据
            //元数据:描述结果集数据的数据 , 简单讲,就是这个结果集有哪些列,什么类型等等

            ResultSetMetaData rsmd = rs.getMetaData();
            //获取结果集的列数
            int columnCount = rsmd.getColumnCount();
            //6.解析rs
            if(rs.next()){
                T entity = (T)entityClass.newInstance();

                for(int i = 0 ; i<columnCount;i++){
                    String columnName = rsmd.getColumnName(i+1);            //fid   fname   price
                    Object columnValue = rs.getObject(i+1);     //33    苹果      5
                    setValue(entity,columnName,columnValue);
                }
                return entity ;
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new DAOException("BaseDAO load出错了");
        }

        return null ;
    }

    //执行查询,返回List
    protected List<T> executeQuery(String sql , Object... params){
        List<T> list = new ArrayList<>();
        conn = getConn() ;
        try{
            psmt = conn.prepareStatement(sql);
            setParams(psmt,params);
            rs = psmt.executeQuery();

            //通过rs可以获取结果集的元数据
            //元数据:描述结果集数据的数据 , 简单讲,就是这个结果集有哪些列,什么类型等等

            ResultSetMetaData rsmd = rs.getMetaData();
            //获取结果集的列数
            int columnCount = rsmd.getColumnCount();
            //6.解析rs
            while(rs.next()){
                T entity = (T)entityClass.newInstance();

                for(int i = 0 ; i<columnCount;i++){
                    String columnName = rsmd.getColumnLabel(i+1);            //fid   fname   price
                    Object columnValue = rs.getObject(i+1);     //33    苹果      5
//                    System.out.println("columnName==>"+columnName+",columnValue=>"+columnValue);
                    setValue(entity,columnName,columnValue);
                }
                list.add(entity);
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new DAOException("BaseDAO executeQuery出错了");
        }
        return list ;
    }
}

UserDao.java
package com.atguigu.book.dao;

import com.atguigu.book.pojo.User;

public interface UserDAO {
    User getUser(String uname , String pwd );
    void addUser(User user);
    User getUser(String uname);
}

UserDaoImpl类,继承了BaseDao实现了UserDao类
package com.atguigu.book.dao.impl;

import com.atguigu.book.dao.UserDAO;
import com.atguigu.book.pojo.User;
import com.atguigu.myssm.basedao.BaseDAO;

public class UserDAOImpl extends BaseDAO<User> implements UserDAO {
    @Override
    public User getUser(String uname, String pwd) {
        return load("select * from t_user where uname like ? and pwd like ? " , uname , pwd );
    }

    @Override
    public void addUser(User user) {
        executeUpdate("insert into t_user values(0,?,?,?,0)",user.getUname(),user.getPwd(),user.getEmail()) ;
    }

    @Override
    public User getUser(String uname) {
        return load("select * from t_user where uname = ?" , uname);
    }
}
编写Service层
package com.atguigu.book.service;

import com.atguigu.book.pojo.User;

public interface UserService {
    User login(String uname , String pwd );
    void regist(User user);
    User getUser(String uname);
}

具体实现类UserServiceImpl

package com.atguigu.book.service.impl;

import com.atguigu.book.dao.UserDAO;
import com.atguigu.book.pojo.User;
import com.atguigu.book.service.UserService;

public class UserServiceImpl implements UserService {

    private UserDAO userDAO ;

    @Override
    public User login(String uname, String pwd) {
        return userDAO.getUser(uname,pwd);
    }

    @Override
    public void regist(User user) {
        userDAO.addUser(user);
    }

    @Override
    public User getUser(String uname) {
        return userDAO.getUser(uname);
    }
}

编写web层(servlet

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6HUXWSq1-1654307516216)(image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Vkd2FyZHd6dw==,size_16,color_FFFFFF,t_70.png)]

ViewBaseServlet

package com.atguigu.myssm.myspringmvc;

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ViewBaseServlet extends HttpServlet {

    private TemplateEngine templateEngine;

    @Override
    public void init() throws ServletException {

        // 1.获取ServletContext对象
        ServletContext servletContext = this.getServletContext();

        // 2.创建Thymeleaf解析器对象
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);

        // 3.给解析器对象设置参数
        // ①HTML是默认模式,明确设置是为了代码更容易理解
        templateResolver.setTemplateMode(TemplateMode.HTML);

        // ②设置前缀
        String viewPrefix = servletContext.getInitParameter("view-prefix");

        templateResolver.setPrefix(viewPrefix);

        // ③设置后缀
        String viewSuffix = servletContext.getInitParameter("view-suffix");

        templateResolver.setSuffix(viewSuffix);

        // ④设置缓存过期时间(毫秒)
        templateResolver.setCacheTTLMs(60000L);

        // ⑤设置是否缓存
        templateResolver.setCacheable(true);

        // ⑥设置服务器端编码方式
        templateResolver.setCharacterEncoding("utf-8");

        // 4.创建模板引擎对象
        templateEngine = new TemplateEngine();

        // 5.给模板引擎对象设置模板解析器
        templateEngine.setTemplateResolver(templateResolver);

    }

    protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 1.设置响应体内容类型和字符集
        resp.setContentType("text/html;charset=UTF-8");

        // 2.创建WebContext对象
        WebContext webContext = new WebContext(req, resp, getServletContext());

        // 3.处理模板数据
        templateEngine.process(templateName, webContext, resp.getWriter());
    }
}
package com.atguigu.myssm.myspringmvc;

import com.atguigu.myssm.ioc.BeanFactory;
import com.atguigu.myssm.util.StringUtil;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

@WebServlet("*.do")
public class DispatcherServlet extends ViewBaseServlet{

    private BeanFactory beanFactory ;

    public DispatcherServlet(){
    }

    public void init() throws ServletException {
        super.init();
        //之前是在此处主动创建IOC容器的
        //现在优化为从application作用域去获取
        //beanFactory = new ClassPathXmlApplicationContext();
        ServletContext application = getServletContext();
        Object beanFactoryObj = application.getAttribute("beanFactory");
        if(beanFactoryObj!=null){
            beanFactory = (BeanFactory)beanFactoryObj ;
        }else{
            throw new RuntimeException("IOC容器获取失败!");
        }
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置编码
        //request.setCharacterEncoding("UTF-8");
        //假设url是:  http://localhost:8080/pro15/hello.do
        //那么servletPath是:    /hello.do
        // 我的思路是:
        // 第1步: /hello.do ->   hello   或者  /fruit.do  -> fruit
        // 第2步: hello -> HelloController 或者 fruit -> FruitController
        String servletPath = request.getServletPath();
        servletPath = servletPath.substring(1);
        int lastDotIndex = servletPath.lastIndexOf(".do") ;
        servletPath = servletPath.substring(0,lastDotIndex);

        Object controllerBeanObj = beanFactory.getBean(servletPath);


        String operate = request.getParameter("operate");
        if(StringUtil.isEmpty(operate)){
            operate = "index" ;
        }

        try {
            Method[] methods = controllerBeanObj.getClass().getDeclaredMethods();
            for(Method method : methods){
                if(operate.equals(method.getName())){
                    //1.统一获取请求参数

                    //1-1.获取当前方法的参数,返回参数数组
                    Parameter[] parameters = method.getParameters();
                    //1-2.parameterValues 用来承载参数的值
                    Object[] parameterValues = new Object[parameters.length];
                    for (int i = 0; i < parameters.length; i++) {
                        Parameter parameter = parameters[i];
                        String parameterName = parameter.getName() ;
                        if("arg0".equals(parameterName)){
                            parameterName = method.getName();
                        }
                        //如果参数名是request,response,session 那么就不是通过请求中获取参数的方式了
                        if("request".equals(parameterName)){
                            parameterValues[i] = request ;
                        }else if("response".equals(parameterName)){
                            parameterValues[i] = response ;
                        }else if("session".equals(parameterName)){
                            parameterValues[i] = request.getSession() ;
                        }else{
                            //从请求中获取参数值
                            String parameterValue = request.getParameter(parameterName);
                            String typeName = parameter.getType().getName();

                            Object parameterObj = parameterValue ;

                            if(parameterObj!=null) {
                                if ("java.lang.Integer".equals(typeName)) {
                                    parameterObj = Integer.parseInt(parameterValue);
                                }
                            }

                            parameterValues[i] = parameterObj ;
                        }
                    }
                    //2.controller组件中的方法调用
                    method.setAccessible(true);
                    Object returnObj = method.invoke(controllerBeanObj,parameterValues);
                    //3.视图处理
                    String methodReturnStr = (String)returnObj ;
                    if(StringUtil.isEmpty(methodReturnStr)){
                        return ;
                    }
                    if(methodReturnStr.startsWith("redirect:")){        //比如:  redirect:fruit.do
                        String redirectStr = methodReturnStr.substring("redirect:".length());
                        response.sendRedirect(redirectStr);
                    }else if(methodReturnStr.startsWith("json:")){
                        response.setCharacterEncoding("utf-8");
                        response.setContentType("application/json;charset=utf-8");
                        String jsonStr = methodReturnStr.substring("json:".length());
                        PrintWriter out = response.getWriter();
                        out.print(jsonStr);
                        out.flush();
                    }else{
                        super.processTemplate(methodReturnStr,request,response);    // 比如:  "edit"
                    }
                }
            }

            /*
            }else{
                throw new RuntimeException("operate值非法!");
            }
            */
        } catch (Exception e) {
            e.printStackTrace();
            throw new DispatcherServletException("DispatcherServlet出错了...");
        }
    }
}

// 常见错误: IllegalArgumentException: argument type mismatch

UserServet类:用于实现用户登录,用户注册等功能

package com.atguigu.web;



 



import com.atguigu.pojo.User;



import com.atguigu.service.UserService;



import com.atguigu.service.impl.UserServiceImpl;



import com.atguigu.utils.WebUtils;



import com.google.gson.Gson;



 



import javax.servlet.ServletException;



import javax.servlet.http.HttpServletRequest;



import javax.servlet.http.HttpServletResponse;



import java.io.IOException;



import java.lang.reflect.Method;



import java.util.HashMap;



import java.util.Map;



 



import static com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY;



 



public class UserServlet extends BaseServlet {



    private UserService userService=new UserServiceImpl();



    @Override



    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {



        String action = req.getParameter("action");



        try {



            Method method = this.getClass().getDeclaredMethod(action,



                    HttpServletRequest.class,HttpServletResponse.class);



            method.invoke(this,req,resp);



        } catch (Exception e) {



            e.printStackTrace();



        }



    }



    protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {



        String username=req.getParameter("username");



        String password=req.getParameter("password");



        User login = userService.login(new User(null, username, password, null));



        if(login!=null){



            //System.out.println("登陆成功!");



            req.getSession().setAttribute("user",login);



            req.getRequestDispatcher("/pages/user/login_success.jsp").forward(req,resp);



        }else{



            //System.out.println("用户名或密码错误!");



            //把错误信息,和回显的表单项信息,保存到Request域中



            req.setAttribute("msg","用户名或密码错误!");



            req.setAttribute("username",username);



            req.getRequestDispatcher("/pages/user/login.jsp").forward(req,resp);



        }



    }



    protected void regist(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {



        //获取Session中的验证码



        String token =(String)req.getSession().getAttribute(KAPTCHA_SESSION_KEY);



        //删除Session中的验证码



        req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);



        //1.获取请求的参数。比如用户名密码邮箱验证码等



        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());



 



        //2.检查验证码是否正确



        if(token!=null&&token.equalsIgnoreCase(code)){



            //  正确 3检查用户名是否可用



            if(userService.existsUsername(username)){



                //不可用 跳转到注册页面



                //System.out.println("用户名"+username+"已存在!");



                req.setAttribute("msg","用户名已存在");



                req.setAttribute("username",username);



                req.setAttribute("email",email);



                req.getRequestDispatcher("/pages/user/regist.jsp").forward(req,resp);



            }else{



                //可用  调用Service保存到数据库,跳转到登陆成功页面



                userService.registUser(user);



                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);



        }



    }



    /*



    注销用户



     */



    protected void logout(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {



        //1.销毁Session中的用户登陆信息



        //2.重定向到首页



        req.getSession().invalidate();



        resp.sendRedirect(req.getContextPath());



    }



 



    /*



     */



    protected void ajaxExistsUsername(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {



        //获取请求的参数username



        String username = req.getParameter("username");



        //调用userservice.existsUsername();



        boolean existsUsername = userService.existsUsername(username);



        //把返回的结果封装成map对象



        Map<String,Object> resultMap=new HashMap<>();



        resultMap.put("existsUsername",existsUsername);



        Gson gson = new Gson();



        String json = gson.toJson(resultMap);



        resp.getWriter().write(json);



    }



}
第三阶段:编写html页面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="UTF-8" />
    <title>尚硅谷会员注册页面</title>
    <link type="text/css" rel="stylesheet" th:href="@{/static/css/style.css}" />
    <link rel="stylesheet" th:href="@{/static/css/register.css}"/>
    <style type="text/css">
      .login_form {
        height: 420px;
        margin-top: 25px;
      }
    </style>
    <script language="JavaScript" th:src="@{/static/script/regist.js}"></script>
  </head>
  <body>
    <div id="login_header">
      <a href="../index.html">
        <img class="logo_img" alt="" th:src="@{/static/img/logo.gif}" />
      </a>
    </div>

    <div class="login_banner">
      <div class="register_form">
        <h1>注册尚硅谷会员</h1>
        <form th:action="@{/user.do}" method="post" onsubmit="return preRegist() ;">
          <input type="hidden" name="operate" value="regist"/>
          <div class="form-item">
            <div>
              <label>用户名称:</label>
              <input id="unameTxt" type="text" placeholder="请输入用户名" name="uname" value="hello2022" onblur="ckUname(this.value)"/>
            </div>
            <span id="unameSpan" class="errMess">用户名应为6~16位数字和字母组成</span>
          </div>
          <div class="form-item">
            <div>
              <label>用户密码:</label>
              <input id="pwdTxt" type="password" placeholder="请输入密码" name="pwd" value="ok"/>
            </div>
            <span id="pwdSpan" class="errMess">密码的长度至少为8位</span>
          </div>
          <div class="form-item">
            <div>
              <label>确认密码:</label>
              <input id="pwdTxt2" type="password" placeholder="请输入确认密码" value="ok"/>
            </div>
            <span id="pwdSpan2" class="errMess">密码两次输入不一致</span>
          </div>
          <div class="form-item">
            <div>
              <label>用户邮箱:</label>
              <input id="emailTxt" type="text" placeholder="请输入邮箱" name="email" value="bao@126.com"/>
            </div>
            <span id="emailSpan" class="errMess">请输入正确的邮箱格式</span>
          </div>
          <div class="form-item">
            <div>
              <label>验证码:</label>
              <div class="verify">
                <input type="text" name="verifyCode" placeholder="" />
                <img th:src="@{/kaptch.jpg}" alt="" />
              </div>
            </div>
            <span class="errMess">请输入正确的验证码</span>
          </div>
          <button class="btn">注册</button>
        </form>
      </div>
    </div>
    <div id="bottom">
      <span>
        尚硅谷书城.Copyright &copy;2015
      </span>
    </div>
  </body>
</html>

编写js
function $(id){
    return document.getElementById(id);
}

function preRegist(){
    //用户名不能为空,而且是6~16位数字和字母组成
    var unameReg = /[0-9a-zA-Z]{6,16}/;
    var unameTxt = $("unameTxt");
    var uname = unameTxt.value ;
    var unameSpan = $("unameSpan");
    if(!unameReg.test(uname)){
        unameSpan.style.visibility="visible";
        return false ;
    }else{
        unameSpan.style.visibility="hidden";
    }

    //密码的长度至少为8位
    var pwdTxt = $("pwdTxt");
    var pwd = pwdTxt.value ;
    var pwdReg = /[\w]{8,}/; // /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,}$/;
    var pwdSpan = $("pwdSpan");
    if(!pwdReg.test(pwd)){
        pwdSpan.style.visibility="visible";
        return false ;
    }else{
        pwdSpan.style.visibility="hidden";
    }

    //密码两次输入不一致
    var pwd2 = $("pwdTxt2").value ;
    var pwdSpan2 = $("pwdSpan2") ;
    if(pwd2!=pwd){
        pwdSpan2.style.visibility="visible";
        return false ;
    }else{
        pwdSpan2.style.visibility="hidden";
    }

    //请输入正确的邮箱格式
    var email = $("emailTxt").value ;
    var emailSpan = $("emailSpan");
    var emailReg = /^[a-zA-Z0-9_\.-]+@([a-zA-Z0-9-]+[\.]{1})+[a-zA-Z]+$/;
    if(!emailReg.test(email)){
        emailSpan.style.visibility="visible";
        return false ;
    }else{
        emailSpan.style.visibility="hidden";
    }

    return true ;
}

//如果想要发送异步请求,我们需要一个关键的对象 XMLHttpRequest
var xmlHttpRequest ;

function createXMLHttpRequest(){
    if(window.XMLHttpRequest){
        //符合DOM2标准的浏览器 ,xmlHttpRequest的创建方式
        xmlHttpRequest = new XMLHttpRequest() ;
    }else if(window.ActiveXObject){//IE浏览器
        try{
            xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
        }catch (e) {
            xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP")
        }
    }
}

function ckUname(uname){
    createXMLHttpRequest();
    var url = "user.do?operate=ckUname&uname="+uname ;
    xmlHttpRequest.open("GET",url,true);
    //设置回调函数
    xmlHttpRequest.onreadystatechange = ckUnameCB ;
    //发送请求
    xmlHttpRequest.send();
}

function ckUnameCB(){
    if(xmlHttpRequest.readyState==4 && xmlHttpRequest.status==200){
        //xmlHttpRequest.responseText 表示 服务器端响应给我的文本内容
        //alert(xmlHttpRequest.responseText);
        var responseText = xmlHttpRequest.responseText ;
        // {'uname':'1'}
        //alert(responseText);
        if(responseText=="{'uname':'1'}"){
            alert("用户名已经被注册!");
        }else{
            alert("用户名可以注册!");
        }
    }
}

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值