Web应用项目开发

一、Web应用项目开发介绍

  Web应用项目开发的目标是创建交互性强、功能丰富的应用程序,通过浏览器访问。这些应用可以是电子商务网站、社交媒体平台、在线学习系统、博客和论坛等。开发过程包括设计用户界面、处理数据交互、管理用户身份验证和权限、与数据库交互、实现业务逻辑等。

 1.2: Web应用项目开发涉及多个方面的知识和技能

  

  1. 前端开发:前端开发主要关注用户界面和用户体验。您可以学习HTML、CSS和JavaScript等技术,掌握网页布局、样式设计和交互效果等。

  2. 后端开发:后端开发处理服务器端的逻辑和数据存储。您可以学习一种或多种后端语言,如Python、Java、PHP或Ruby等,并了解数据库的基本知识。

  3. 数据库管理:了解数据库的基本原理和常用的数据库系统,如MySQL、PostgreSQL或MongoDB等。学习如何设计和优化数据库模型,以及如何使用SQL语言进行查询和操作数据。

  4. 网络和服务器管理:了解网络协议、HTTP通信和服务器配置等内容,以便正确部署和管理Web应用项目。

  5. 版本控制系统:掌握使用版本控制系统如Git进行代码管理,能够合作开发和管理代码的不同版本。

  6. 安全性和性能优化:学习如何确保Web应用的安全性,包括用户认证、数据加密和防止常见的网络攻击。此外,了解如何通过优化代码和资源管理来提高Web应用的性能。

1.3:Web应用项目开发学习路线

  

学习Web应用项目开发的路线可以按照以下步骤进行:

  1. 学习HTML、CSS和JavaScript:这是Web开发的基础,HTML用于创建网页结构,CSS用于设计页面样式,JavaScript用于实现交互效果和动态功能。您可以通过在线教程、书籍或在线课程学习这些技术。

  2. 掌握前端框架和库:学习流行的前端框架和库,如React、Vue.js或Angular等,可以帮助您更高效地构建复杂的用户界面和应用逻辑。了解它们的工作原理和基本用法,并实践使用它们开发一些小型项目。

  3. 学习后端开发语言:选择一种后端开发语言,如Python、Java、Ruby或PHP等,并深入学习该语言的核心概念和语法。了解如何处理HTTP请求、数据存储和服务器端逻辑等。

  4. 学习数据库管理:学习SQL语言和常见的关系型数据库系统,如MySQL、PostgreSQL或Oracle等。了解如何设计数据库模型、执行查询和更新操作,以及优化数据库性能。

  5. 学习服务器和网络知识:了解基本的服务器配置和管理,包括Linux操作系统、网络协议、域名系统(DNS)等。学习如何部署Web应用项目到服务器上,并确保安全性和可靠性。

  6. 学习版本控制和团队协作:了解版本控制系统如Git的基本用法,可以帮助您管理项目代码并与团队成员合作开发。学习分支管理、代码合并和冲突解决等技巧。

  7. 理解Web应用安全和性能优化:学习常见的Web安全漏洞和攻击方式,并了解如何保护Web应用的安全性。此外,学习如何优化代码和资源,以提高Web应用的性能和响应速度。

  8. 实践项目开发:通过实际的项目开发经验来巩固所学知识。可以从简单的练习项目开始,逐渐挑战更复杂的实际场景,从而提升自己的技能和经验。

记住,持续的实践和不断的学习是成为一名优秀的Web应用程序员的关键。同时,参与开源项目、阅读技术文档和与其他开发者交流也是提升自己的好方法。

  二、Web应用项目开发环境配置

要进行Web应用项目开发,您需要配置以下环境:

  1. 开发工具和编辑器:选择一种适合您的编程语言和偏好的集成开发环境(IDE)或文本编辑器。一些常见的选择包括Visual Studio Code、PyCharm、Eclipse、Sublime Text等。

  2. 前端开发环境:对于前端开发,您需要一个浏览器用于调试和测试您的网页。同时,您可以使用Node.js作为运行环境,以便在本地模拟服务器环境。

  3. 后端开发环境:根据您选择的后端开发语言,需要安装相应的运行时环境和开发工具。例如,如果您选择Python作为后端语言,您需要安装Python解释器和相关的开发工具,如pip包管理器和虚拟环境工具。

  4. 数据库:如果您的Web应用项目需要使用数据库,您需要安装和配置数据库系统,如MySQL、PostgreSQL、MongoDB等。您还可以选择使用数据库管理工具来方便地管理和操作数据库。

  5. 版本控制系统:配置一个版本控制系统,如Git,用于管理和跟踪您的代码变更。您可以选择在本地设置Git仓库,或者使用在线的代码托管平台,如GitHub、GitLab或Bitbucket。

  6. 服务器环境:如果您计划将Web应用部署到生产环境中,您需要配置服务器环境。这包括选择和设置适当的操作系统、Web服务器(如Apache或Nginx)和应用服务器(如Tomcat或Gunicorn)。

  7. 其他工具和库:根据您的具体项目需求,可能需要安装其他工具和库来支持开发和部署。例如,前端框架(如React或Vue.js)、后端框架(如Django或Ruby on Rails)或其他第三方库。

请注意,具体的环境配置可能因个人偏好、项目需求和技术栈而有所不同。建议在开始之前仔细研究并了解您所选技术栈的相关环境要求,并按照官方文档或社区指南进行配置。

三、Web应用项目开发功能模块的实现

3.1:用户管理模块设计及实现

3.1.1与用户管理需求

  对于任何一个管理系统,用户管理功能都是必不可少的。通常,在使用系统之前,用户需要先注册。在使用过程中,往往还存在修改需求,如修改个人联系方式、收货地址等。

在线书店管理系统中主要有两类用户——普通用户和管理员。

  • 普通用户的操作包括用户注册、用户登录、用户退出和用户个人信息修改等。

  • 管理员的操作包括用户登录、用户退出和用户管理(包括新增普通用户、对普通用户的信息进行编辑和删除普通用户)等。

本章中,我们将实现用户注册、用户登录和用户管理等功能。

普通用户在首次使用系统之前,需要注册,建立个人账户,此时需要提供必要的个人信息,如登录账号、密码、全名、电话、收货地址等,以便完成图书的支付和购买流程。普通用户注册流程如下图所示。

  用户登录系统,输入用户名和密码后,系统会验证用户角色,因为系统需要知道此时登录的用户是管理员还是普通用户。若系统验证其为普通用户,则进入普通用户登录后的页面;若是管理员,则进入管理员管理页面;否则,系统提示用户名或密码错误的信息。用户登录流程如下图所示。

  本系统有两种角色,一种是管理员,二种是普通用户。管理员可以新增和删除普通用户,并且可以对普通用户的信息进行编辑。用户管理流程如下图:

3.1.2接口需求分析

针对用户管理要求,我们定义如下接口。

  1. 用户注册接口。

  • 接口名称:/registration

  • 接口参数:User类的对象

  • 返回类型:若注册成功,则返回/login页面;否则,返回registration(注册)页面。

  1. 用户信息查询接口。

  • 接口名称:/profile。利用GET方式获取用户信息。

  • 接口参数:用户信息。

  • 返回类型:若查询到用户信息,则返回/profile页面。

  1. 用户信息编辑接口。

  • 接口名称:/users/edit/{userId}。

  • 接口参数:User类的对象。

  • 返回类型:若用户信息修改成功,则返回修改后信息的/profile页面。

  1. 用户添加接口。

  • 接口名称:/user/add。利用POST方式添加用户信息。

  • 接口参数:User类的对象。

  • 返回类型:若用户添加成功,则返回/addUser页面。

  1. 用户删除接口

  • 接口名称:/users/delete/{userId}。利用DELETE方式删除用户。

  • 接口参数:userId(用户ID)。

  • 返回类型:返回用户列表(showAllUsers)页面。

3.2后端设计及编码

本节介绍用户域模型设计、Repository实现、用户服务接口实现和控制层实现。

3.2.1用户域模型设计

创建com.book.shop.model包,增加User类,基于user表进行用户域模型的设计,通过定义User类的对象实现序列化。

@Entity
@Table(name = "user")
public class User implements Serializable {
    private static final long serialVersionUID =1L;
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)    //定义主键,自增长类型
    @Column(name ="userid")
    private long userId;

    @NotNull
    @Size(min =1, max =50)
    @Column(name = "username", length =50, unique = true, nullable = false )
    private String userName;

    @NotNull
    @Column(name="password", length = 60)               //用户密码
    private String userPassword;

    @Size(max=50)                                       //用户全名
    @Column(name = "fullname",length = 50)
    private String userFullname;

    @Size(max=50)                                      //用户电话
    @Column(name = "phone",length = 50)
    private String userPhone;

    @Size(max = 120)                                  //用户地址
    @Column(name="address",length = 120)
    private String userAddress;

    @Size(max=80)                                    //用户银行卡号
    @Column(name= "bankcard",length = 80)
    private String userBankcard;



    //建立user表和roles表之间多对多的映射关系
    @ManyToMany(cascade = {CascadeType.PERSIST,CascadeType.MERGE})
    @JoinTable(
            name = "permission",
            joinColumns = {@JoinColumn(name = "userid",referencedColumnName ="userid")},
            inverseJoinColumns = {@JoinColumn(name = "role",referencedColumnName = "rolename")}
    )
    private Set<Roles> roles =new HashSet<>();


    public long getUserId() {
        return userId;
    }

    public void setUserId(long userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPassword() {
        return userPassword;
    }

    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }

    public String getUserFullname() {
        return userFullname;
    }

    public void setUserFullname(String userFullname) {
        this.userFullname = userFullname;
    }

    public String getUserPhone() {
        return userPhone;
    }

    public void setUserPhone(String userPhone) {
        this.userPhone = userPhone;
    }

    public String getUserAddress() {
        return userAddress;
    }

    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }

    public String getUserBankcard() {
        return userBankcard;
    }

    public void setUserBankcard(String userBankcard) {
        this.userBankcard = userBankcard;
    }

    public Set<Roles> getRoles() {
        return roles;
    }

    public void setRoles(Set<Roles> roles) {
        this.roles = roles;
    }

    public User(long userId, String userName, String userPassword, String userFullname, String userPhone, String userAddress, String userBankcard, Set<Roles> roles) {
        this.userId = userId;
        this.userName = userName;
        this.userPassword = userPassword;
        this.userFullname = userFullname;
        this.userPhone = userPhone;
        this.userAddress = userAddress;
        this.userBankcard = userBankcard;
        this.roles = roles;
    }

    public User() {

    }

    @Override
    public String toString() {
        return "User{" +
                "userId=" + userId +
                ", userName='" + userName + '\'' +
                ", userPassword='" + userPassword + '\'' +
                ", userFullname='" + userFullname + '\'' +
                ", userPhone='" + userPhone + '\'' +
                ", userAddress='" + userAddress + '\'' +
                ", userBankcard='" + userBankcard + '\'' +
                ", roles=" + roles +
                '}';
    }
    //重载equals()方法,实现user类
    @Override
    public boolean equals(Object obj){
        if (this == obj)
            return true;
        if(!(obj instanceof User)) return false;
        User user =(User) obj;
        return Objects.equals(getUserId(),user.getUserId());
    }
    //重载hashCode()方法
    @Override
    public int hashCode(){
        return Objects.hash(getUserId());
    }
}

Roles实体

@Data
@Entity
@Table(name = "roles")
public class Roles implements Serializable {
    @Id
    @Column(name ="rolename")
    private String rolename;
}

Order实体

@Data
@Entity
@Table(name = "orders")
public class Order implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)    //定义主键,自增长类型
    @Column(name ="orderid")
    private Long orderid;

    @NotNull
    @Column(name="userid")
    private int userId;

    @NotNull
    @Column(name="orderdate")
    private Timestamp orderdate;

    @Column(name="status",nullable = false)
    private byte status;

    @Column(name="totalprice",precision = 5,scale = 1)
    private BigDecimal totalprice;


    public Order(Long orderid, int userid, Timestamp orderdate, byte status, BigDecimal totalprice) {
        this.orderid = orderid;
        this.userId = userid;
        this.orderdate = orderdate;
        this.status = status;
        this.totalprice = totalprice;
    }

    public Order(){

    }
3.2.2用户Repository接口
@Repository
public interface UserRepository extends JpaRepository<User,Long> {

    public User findByUserName(String userName);

    @EntityGraph(attributePaths = "roles")
    public User findOneWithRolesByUserName(String userName);
}

RolesRepository接口

@Repository
public interface RolesRepository extends JpaRepository<Roles, String> {

}

OrderRepository接口

@Repository
public interface OrderRepository extends JpaRepository<Order,Long> {
   
}
3.2.3用户服务接口实现
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private RolesRepository rolesRepository;
    @Autowired
    private OrderRepository orderRepository;

    //通过用户名查找用户
    public User findByUserName(String userName){
        return userRepository.findByUserName(userName);
    }
    //注册用户
    public User registerUser(User user){
        User newUser = new User();
        Optional<Roles> role_user = rolesRepository.findById("ROLE_USER");
        Roles role = role_user.get();
        Set<Roles> roles = new HashSet<>();
        BCryptPasswordEncoder encryptedPassword = new BCryptPasswordEncoder();
        String encode = encryptedPassword.encode(user.getUserPassword());
        newUser.setUserName(user.getUserName());
        newUser.setUserPassword(encode);
        newUser.setUserFullname(user.getUserFullname());
        newUser.setUserPhone(user.getUserPhone());
        newUser.setUserAddress(user.getUserAddress());
        newUser.setUserBankcard(user.getUserBankcard());
        roles.add(role);
        newUser.setRoles(roles);
        userRepository.save(newUser);
        return newUser;
    }

   //更新用户信息
   public void updateUser(User user){
        User updateUser = userRepository.findById(user.getUserId()).get();
        updateUser.setUserFullname(user.getUserFullname());
        updateUser.setUserAddress(user.getUserAddress());
        updateUser.setUserPhone(user.getUserPhone());
        updateUser.setUserBankcard(user.getUserBankcard());
        userRepository.save(updateUser);
   }
   //查找所有用户信息
   public List<User> findAllUsers(){
        return userRepository.findAll();
   }
    //通过id查找
   public User findUserById(Long userId){
        return userRepository.findById(userId).get();
   }
    //通过用户id删除
    public void deleteUserById(Long userId){
        userRepository.deleteById(userId);
    }
    //查询用户对应的订单数量,有订单号的用户不允许删除
   public int getUserOrderAmount(Long userId){
       List<Order> order = orderRepository.findByUserId(userId);
       if(order==null){
           return 0;
       }
       else {
           return order.size();

       }
   }

}
3.2.4用户控制层实现
@Controller
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private OrderService orderService;

    @GetMapping("/login")
    public String login(Principal principal){
        if(principal == null){
            return "login/login";
        }
            return "redirect:/";
    }
    //用户注册接口
    @GetMapping("/registration")
    public String registration(Model model){
        User user =new User();
        model.addAttribute("user",user);
        return "login/registration";
    }
    //用户注册接口
    @PostMapping("/registration")
    //@valid用于验证注解是否符合要求,直接加在变量user之前,
    // 在变量中添加验证信息的要求,当不符合要求时就会在方法中返回message的错误提示信息。
    public String createUser(@Valid User user, BindingResult bindingResult, Model model){
        User newUser = userService.findByUserName(user.getUserName());
        if(newUser != null){
            bindingResult.rejectValue("userName","error.user","用户已经存在");
        }
        if(!bindingResult.hasErrors()){
            userService.registerUser(user);
            model.addAttribute("successMessage","用户注册成功");
            model.addAttribute("user",new User());
        }
        return "login/registration";
    }
    //用户创建
    @PostMapping("/users")
    @Secured("ROLE_ADMIN")
    public String createUser(@RequestBody User user, Model model){
        if(user.getUserId()!=0){
            model.addAttribute("message","用户信息不存在");
        }else if(userService.findByUserName(user.getUserName())!= null){
            model.addAttribute("messgae","用户名存在");
        }else{
            userService.registerUser(user);
            model.addAttribute("message","用户创建成功");
        }
        return "edit/editUser";
    }
    //获取当前登录用户信息
    @GetMapping("/profile")
    public String getCurrentUser(Principal principal,Model model){
        if(principal == null){
            return "redirect:/";
        }
        User user = userService.findByUserName(principal.getName());
        model.addAttribute("user",user);
        return "edit/profile";
    }
    //更新用户信息
    @PostMapping("/profile")
    public String updateUser(@ModelAttribute User user,BindingResult bindingResult,Model model,Principal principal){
        User userExists= userService.findByUserName(user.getUserName());
        if(userExists != null&& !Objects.equals(userExists.getUserName(),principal.getName())){
            bindingResult.rejectValue("userName","error.user","用户名重复");
        }
        if(!bindingResult.hasErrors()){
            userService.updateUser(user);
            model.addAttribute("successMessage","用户信息更新成功");
        }
        return getCurrentUser(principal,model);
    }

    //获取所有用户信息查询接口
    @GetMapping("/users")
    @Secured("ROLE_ADMIN")
    public String getUsers(Model model){
        List<User> users = userService.findAllUsers();
        model.addAttribute("users",users);
        return "edit/showAllUsers";
    }
    //添加用户
    @GetMapping("/users/add")
    @Secured("ROLE_ADMIN")
    public String addUserPage(Model model){
        User user = new User();
        model.addAttribute("user",user);
        return "edit/addUser";
    }
    //添加用户
    @PostMapping("/users/add")
    @Secured("ROLE_ADMIN")
    public String addUser(@ModelAttribute User user, Model model, BindingResult bindingResult){
        User userExists = userService.findByUserName(user.getUserName());
        if(userExists!= null){
            bindingResult.rejectValue("userName","error.user","用户已存在");
        }
        if(!bindingResult.hasErrors()){
            User newUser =userService.registerUser(user);
            model.addAttribute("successMessage","创建用户成功,用户Id:"+newUser.getUserId());
            model.addAttribute("user",new User());
        }
        return "edit/addUser";
    }
    //通过id编辑用户
    @GetMapping("/users/edit/{userId}")
    @Secured ("ROLE_ADMIN")
    public String editUserPage(@PathVariable Long userId, Model model){
        User user = userService.findUserById(userId);
        model.addAttribute("user", user);
        System.out.println(user);
        return "edit/editUser";
    }
    @PostMapping("/users/edit")
    @Secured ("ROLE_ADMIN")
    public String editUser(@ModelAttribute User user, Model model) {
        userService.updateUser(user);
        model.addAttribute("successMessage","用户更新"+user.getUserId());
        return editUserPage(user.getUserId(), model);
    }
    //通过id删除指定用户
    @GetMapping("/users/delete/{userId}")
    @Secured ("ROLE_ADMIN")
    public String deleteUser(@PathVariable Long userId, Model model){
        int userOrderAmount = userService.getUserOrderAmount(userId);
        if (userOrderAmount > 0) {
            model.addAttribute("Message", "该用户名下有"+userOrderAmount+"条订单,不能删除");
        }
        else{
//            userService.deleteUserById(userId);
            model.addAttribute("Message", "用户编号"+userId+"删除成功");
        }

        return getUsers(model);
    }
}

3.3前端设计及编码

3.3.1用户注册registration.html
<body>
    <div heigth="auto" th:replace="fragments/header :: navbar"></div>
    <div class="container p-5">
        <h3 class="text-center  ">欢迎注册在线书店系统</h3>
        <div class="row justify-content-center">
            <div class="col-4">
                <div class="alert alert-success" th:if="${successMessage}" th:utext="${successMessage}"></div>
                <form class="register-form" name="form" role="form" th:action="@{/registration}" th:object="${user}" method="post">
                    <div class="form-group">
                        <label class="form-control-label" for="login">用户名:</label>
                        <input type="text" class="form-control" id="login" name="login"
                            th:field="*{userName}" required
                               minlength="1" maxlength="50"
                               pattern="^[_'.@A-Za-z0-9-]*$">
                        <div th:if="${#fields.hasErrors('userName')}">
                            <small class="form-text text-danger" th:errors="*{userName}"></small>
                        </div>
                    </div>
                    <div class="form-group" >
                        <label class="form-control-label" for="password">密&nbsp&nbsp&nbsp&nbsp码:</label>
                        <input type="password" class="form-control" id="password" name="password"
                            th:field="*{userPassword}" minlength="4" max="50" required>
                        <div th:if="${#fields.hasErrors('userPassword')}">
                            <small class="form-text text-danger" th:errors="*{userPassword}"></small>
                        </div>
                    </div>
                    <div class="pt-2" >
                        <a class="btn btn-primary" th:href="@{/}">返回首页</a>
                        <button class="btn btn-primary" type="submit">用户注册</button>
                    </div>
                </form>
            </div>
        </div>
    </div>

</body>
3.3.2用户登录login.html
<body>
    <div th:replace="fragments/header :: navbar"></div>
    <div class="container-fluid p-5">
      <h3 class="text-center ">欢迎使用在线书店系统</h3>
      <div class="row justify-content-center">
          <div class="col-4">
            <div class="alert alert-danger" th:if="${param.error}" >
              <strong>无效用户名和密码</strong>
            </div>
            <form class="form" role="form" th:action="@{/login}" method="post">
              <div class="form-group">
                <label for="username">用户名:</label>
                <input type="text" class="form-control" name="username"
                  id="username" placeholder="用户名" required>
              </div>
              <div class="form-group">
                <label for="password">密&nbsp&nbsp&nbsp&nbsp码:</label>
                <input type="password" class="form-control" name="password"
                       id="password" placeholder="密码" required>
              </div>
              <div class="col-12 text-end p-2">
                <button type="submit" class="btn btn-primary">登录</button>
                <a class="btn btn-primary" th:href="@{/registration}">注册</a>
              </div>

            </form>
          </div>
          <div class="row justify-content-center">
              <div class="col-4">
                  <div class="alert alert-warning">
                      <span>还未注册用户吗?请先注册:</span>
                  </div>
              </div>
          </div>
      </div>
    </div>
</body>
3.3.3用户个人信息修改editUser.html
<body>
    <div th:replace="fragments/header :: navbar"></div>
    <div class="container pt-5">
        <div class="row">
            <div class="container">
                <h3 class="text-center">用户个人信息</h3>
                <div class="row d-flex justify-content-center">
                    <div th:fragment="userForm" class="col-md-4">
                        <div class="alert alert-success" th:if="${successMessage}" th:utext="${successMessage}"></div>
                        <form name="userForm" role="form" method="post" th:object="${user}" th:action="@{/users/edit}">
                            <div class="form-group">
                                <input type="hidden" class="form-control" id="id" name="id" th:field="*{userId}"/>
                            </div>
                            <div class="form-group">
                                <label  class="form-control-label" for="login">用户登录名 </label>
                                <input type="text" class="form-control" id="login" name="login" th:field="*{userName}" readonly/>
                            </div>
                            <div class="form-group">
                                <label class="form-control-label" for="userFullname">用户全名</label>
                                <input type="text" class="form-control" id="userFullname" name="userFullname" th:field="*{userFullname}" readonly/>
                            </div>
                            <div class="form-group">
                                <label class="form-control-label" for="userPhone">用户电话</label>
                                <input type="text" class="form-control" id="userPhone" name="userPhone" th:field="*{userPhone}" required
                                    maxlength="11" pattern="^[0-9]*$" />
                                <div th:if="${#fields.hasErrors('userPhone')}">
                                    <small class="form-text text-danger" th:errors="*{userPhone}" ></small>
                                </div>
                            </div>
                            <div class="form-group">
                                <label class="form-control-label" for="userAddress">用户地址</label>
                                <input type="text" class="form-control" id="userAddress" name="userAddress" th:field="*{userAddress}" required
                                       maxlength="120" pattern="^[\u4e00-\u9fa5_a-zA-z-0-9]*$" />
                                <div th:if="${#fields.hasErrors('userAddress')}">
                                    <small class="form-text text-danger" th:errors="*{userAddress}" ></small>
                                </div>
                            </div>
                            <div class="form-group">
                                <label class="form-control-label" for="userBankcard">用户银行卡号</label>
                                <input type="text" class="form-control" id="userBankcard" name="userBankcard" th:field="*{userBankcard}" readonly/>
                            </div>
                            <div class="col-12 text-right">
                                <a type="button" class="btn btn-secondary" th:href="@{/users}">返回</a>
                                <button type="submit" class="btn btn-primary">信息更新</button>
                            </div>
                        </form>

                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
3.3.4用户管理showAllUsers.html
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.2/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js" integrity="sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.min.js" integrity="sha384-ep+dxp/oz2RKF89ALMPGc7Z89QFa32C8Uv1A3TcEK8sMzXVysblLA3+eJWTzPJzT" crossorigin="anonymous"></script>
</head>
<body>
    <div th:replace="fragments/header:: navbar"></div>
    <div class="container pt-5">
    <h3 class="text-center">用户信息汇总</h3>
    <div class="row"> </div>
    <br/>
    <div class="col-6">
        <div class="alert alert-danger" th:if="${Message}" th:utext="${Message}"></div>
    </div>
    <div class="table-responsive">
        <table class="table table-bordered">
            <thead>
            <tr>
                <th>用户编号</th>
                <th>登录名称</th>
                <th>用户全名</th>
                <th>用户电话</th>
                <th>用户地址</th>
                <th>银行卡号</th>
                <th>管理操作</th>
            </tr>
            </thead>
            <tbody>
            <tr th:each="user:${users}">
                <td>[[${user.userId}]]</td>
                <td>[[${user.userName}]]</td>
                <td>[[${user.userFullname}]]</td>
                <td>[[${user.userPhone}]]</td>
                <td>[[${user.userAddress}]]</td>
                <td>[[${user.userBankcard}]]</td>
                <td class="text-start">
                    <div class="btn-group flex-btn-group-container">
                        <a th:href="@{'/users/edit/{userId}'(userId=${user.userId})}"
                           class="btn btn-info btn-sm">
                            <span class="bi bi-eye"></span>
                            <span class="d-none d-md-inline">编辑</span>
                        </a>
                        <a th:href="@{'/users/delete/{userId}'(userId=
                                ${user.userId})}"
                           class="btn btn-danger btn-sm">
                            <span class="bi bi-x"></span>
                            <span class="d-none d-md-inline">删除</span>
                        </a>
                    </div>
                </td>
            </tr>
            </tbody>
        </table>
    </div>
</div>
<div class="col-10 text-end">
    <a class="btn btn-primary" th:href="@{users/add}">新增用户</a>
    <a class="btn btn-primary" th:href="@{/}">返回首页</a>
</div>
</body>
</html>
3.3.5创建用户addUser.html
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<head th:replace="fragments/header :: head"></head>
<body>
<div th:replace="fragments/header :: navbar"></div>
<div class="container pt-5">
    <h3 class="text-center">新增用户</h3>
    <div class="row justify-content-center">
        <div class="col-md-4">
            <div class="alert alert-success" th:if="${successMessage}"
                 th:utext="${successMessage}">
            </div>
            <form name="userForm" role="form" method="post" th:object=
                    "${user}" th:action="@{/users/add}">
                <div class="form-group">
                    <input type="hidden" class="form-control" id="id"
                           name="id" th:field="*{userId}"/>
                </div>

                <div class="form-group">
                    <label class="form-control-label" for="login">登录名称</label>
                    <input type="text" class="form-control" id="login"
                           name="login" th:field="*{userName}" required
                           maxlength="50" pattern="^[_'.@A-Za-z0-9-]*$">
                    <div th:if="${#fields.hasErrors('userName')}">
                        <small class="form-text text-danger" th:errors="*{userName}">
                        </small>
                    </div>
                </div>
                <div class="form-group">
                    <label class="form-control-label" for="userFullname">用户全名</label>
                    <input type="text" class="form-control" id="userFullname"
                           th:field="*{userFullname}" name="userFullname" required
                           maxlength="50" pattern="^[\u4e00-\u9fa5]{0,}*S">
                    <div th:if="${#fields.hasErrors('userFullname')}">
                        <small class="form-text text-danger" th:errors="*{userFullname}">
                        </small>
                    </div>
                </div>
                <div class="form-group">
                    <label class="form-control-label" for="password">用户密码
                    </label>
                    <input type="password" class="form-control" id="password"
                           name="password" th:field="*{userPassword}" maxlength=50>
                    <div th:if="${#fields.hasErrors('userPassword')}">
                        <small class="form-text text-danger" th:errors="*{userPassword}">
                        </small>
                    </div>
                </div>
                <div class="form-group">
                    <label class="form-control-label" for="userPhone">用户电话</label>
                    <input type="text" class="form-control" id="userPhone"
                           th:field="*{userPhone}" name="userPhone" required
                           maxlength="11" pattern="^[0-9]*$">
                    <div th:if="${#fields.hasErrors('userPhone')}">
                        <small class="form-text text-danger" th:errors="*{userPhone}"></small>
                    </div>
                </div>
                <div class="form-group">
                    <label class="form-control-label" for="userAddress">用户地址</label>
                        <input type="text" class="form-control" id="userAddress"
                               th:field="*{userAddress}" name="userAddress" required
                               maxlength="120" pattern= "^[\u4e00-lu9fa5_a-zA-Z0-9]*$">
                        <div th:if="${#fields.hasErrors('userAddress')}">
                            <small class="form-text text-danger" th:errors="*{userAddress}">
                            </small>
                        </div>
                </div>
                <div class="form-group">
                    <label class="form-control-label" for="userBankcard">银行卡号</label>
                        <input type="text" class="form-control" id="userBankcard" th:field="*{userBankcard}"
                               name="userBankcard" required maxlength="80" pattern="^[0-9]*$">
                        <div th:if="${#fields.hasErrors('userBankcard')}">
                            <small class="form-text text-danger" th:errors="*{userBankcard}">
                                </small>
                        </div>
                </div>
            <div class = "col-12 text-right">
                <a type="button" class="btn btn-secondary" th:href="@{/users}">返回</a>
                <button type="submit" class="btn btn-primary">新建</button>
            </div>
        </form>
        </div>
    </div>
</div>
</body>
</html>
3.3.6删除用户
<!--已包含在showAllUsers文件中-->
<a th:href="@{'/users/delete/{userId}'(userId=
        ${user.userId})}"
   class="btn btn-danger btn-sm">
    <span class="bi bi-x"></span>
    <span class="d-none d-md-inline">删除</span>
</a>

四、mybatis与mybatis-plus实现以及它们之间的区别。

  MyBatis 是一个基于 Java 的持久层框架,它通过 XML 或注解的方式将对象与 SQL 语句进行映射,提供了灵活的 SQL 查询和结果映射功能。而 MyBatis-Plus 是 MyBatis 的增强工具包,提供了更多便捷的功能和增强的特性,使得开发人员能够更高效地进行数据库操作。

下面是它们的实现方式和主要区别:

MyBatis 实现:

  1. XML 文件配置: 在 MyBatis 中,通常需要编写 XML 文件来配置 SQL 映射关系,定义 SQL 语句、参数映射以及结果集映射等内容。

  2. SQL 控制: 开发人员需要手动编写 SQL 语句,并在 XML 文件中进行配置,包括 SQL 查询、更新、删除等。

  3. 基本功能: MyBatis 提供了基本的数据库操作功能,包括 SQL 查询、参数绑定、结果集映射等。

MyBatis-Plus 实现:

  1. 基于 MyBatis: MyBatis-Plus 是在 MyBatis 的基础上进行了功能增强和扩展,可以作为 MyBatis 的增强工具包来使用。

  2. 注解支持: MyBatis-Plus 提供了注解方式的配置,简化了 XML 配置文件的编写,提供了更便捷的开发方式。

  3. CRUD 方法封装: MyBatis-Plus 封装了常见的 CRUD(Create, Retrieve, Update, Delete)操作方法,使得开发人员不需要手动编写 SQL 语句,可以通过简单的方法调用来完成数据库操作。

  4. 分页插件: MyBatis-Plus 提供了强大的分页插件,可以方便地进行分页查询操作。

区别和优势:

  1. 开发效率: MyBatis-Plus 在 MyBatis 的基础上提供了更多便捷的功能和方法封装,可以大大提高开发效率,减少重复代码的编写。

  2. 注解支持: MyBatis-Plus 提供了更多的注解支持,简化了 XML 配置文件的编写,使得开发更加便捷。

  3. CRUD 方法封装: MyBatis-Plus 封装了通用的 CRUD 操作方法,可以直接调用,省去了手动编写 SQL 语句的过程。

总的来说,MyBatis-Plus 是 MyBatis 的增强工具包,提供了更多便捷的功能和方法封装,可以大大提高开发效率,特别适合对 CRUD 操作频繁的业务场景。如果您需要快速、高效地进行数据库操作,并且喜欢注解方式的配置,MyBatis-Plus 是一个很好的选择。

五、Web应用项目开发中最常遇见的问题,以及解决方法

性能问题: 应用响应时间慢、负载高等。解决方法包括:

  • 优化数据库查询:使用索引、合理设计表结构。
  • 使用缓存:缓存常用数据、页面片段等。
  • 优化代码:减少循环嵌套、避免重复计算等。

安全问题: 如跨站脚本攻击(XSS)、跨站请求伪造(CSRF)等。解决方法包括:

  • 输入验证和过滤:对用户输入进行验证,并过滤可能的恶意代码。
  • 使用安全框架:如Spring Security,提供身份认证和授权功能。
  • 防御机制:设置合适的响应头、使用验证码等。

跨浏览器兼容性问题: 不同浏览器对CSS和JavaScript的支持不同,导致页面在不同浏览器上显示效果不一致。解决方法包括:

  • 使用CSS Reset:重置浏览器默认样式,保证页面在不同浏览器上的一致性。
  • 使用CSS前缀:为CSS属性添加浏览器厂商前缀,以支持不同浏览器。
  • 使用Polyfills和垫片库:填补浏览器兼容性差异,提供一致的API和功能支持。

部署和环境问题: 在部署到生产环境时遇到配置错误、依赖缺失等问题。解决方法包括:

  • 自动化部署:使用工具如Docker、Kubernetes等进行自动化部署。
  • 环境管理:使用配置管理工具(如Ansible)管理环境配置。
  • 错误日志监控:使用监控工具(如ELK Stack)实时监控应用错误日志。

代码质量问题: 代码冗余、可维护性差、可扩展性差等。解决方法包括:

  • 代码重构:去除冗余代码、提取公共方法等。
  • 代码规范和代码审查:遵循编码规范,进行代码审查和团队合作。
  • 单元测试和集成测试:编写测试用例,保证代码质量和稳定性。

以上是常见的问题及其解决方法,但具体问题还可能因项目需求、技术栈和开发环境而有所不同。在开发过程中,及时调试、排查问题,并参考相关文档和社区讨论,将有助于更快地解决问题。同时,团队协作和经验积累也是解决问题的重要因素。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值