Spring练习

1 Spring环境搭建步骤

①创建工程

②导入静态页面

③导入需要坐标

④创建包结构

⑤导入数据库脚本

⑥创建POJO类

⑦创建配置文件

 

对于⑦重点说明:

配置文件主要是对applicationContext和spring-mvc以及web.xml进行配置。

web.xml:
1)配置Spring监听器

1
2
3
4
5
6
7
8
9
10
<!--  全局的初始化参数  -->
  <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
 
  <!--  Spring监听器  -->
  <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  

作用:ContextLoaderListener会读取这些XML文件并产生 WebApplicationContext对象,然后将这个对象放置在ServletContext的属性

里,这样我们只要可以得到Servlet就可以得到WebApplicationContext对象,并利用这个对象访问spring 容器管理的bean。

2)配置Spring-mvc的前端控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!--  Spring-mvc的前端控制器  -->
  <servlet>
      <servlet-name>DispatcherServlet</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:spring-mvc.xml</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
  </servlet>
 
  <servlet-mapping>
      <servlet-name>DispatcherServlet</servlet-name>
      <url-pattern>/</url-pattern>
  </servlet-mapping>

  

所有请求地址都将经过这个servlet,且优先度为1,由spring-mvc来完成地址的映射和类的注入

关于初始化参数contextConfigLocation的含义,在Spring MVC的学习笔记中有提到。

spring-mvc.xml:

1)mvc注解驱动

1
2
<!--  mvc注解驱动  -->
  <mvc:annotation-driven/>

  

在业务方法返回对象时,会自动将该对象转换成json格式的字符串

2)视图解析器

1
2
3
4
5
<!--  配置视图解析器  -->
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix" value="/pages/"/>
      <property name="suffix" value=".jsp"/>
  </bean>

  

在进行页面跳转时,会自动拼接prefix+xxx+suffix。

3)静态资源开放

1
2
<!--  静态资源开放 如果不开放相关的资源,那么所有的地址请求都将通过Dispatcher适配器找RequestMapping映射,有的资源就无法找到  -->
  <mvc:default-servlet-handler/>

  

在访问非响应体请求时使用默认的适配器。

4)组件扫描

1
2
<!--  组件扫描 扫描Controller  -->
 <context:component-scan base-package="com.xc.controller"/>

  

applicationContext.xml:

1)加载分离出的数据库配置属性

1
2
<!--  加载jdbc.properties资源  -->
<context:property-placeholder location="classpath:jdbc.properties"/>

  

2)配置数据源对象

1
2
3
4
5
6
7
<!--  配置数据源对象   -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${jdbc.driver}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>
    <property name="user" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

  

3)配置JdbcTemplate对象

1
2
3
4
<!-- 配置JdbcTemplate对象   -->
  <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
      <property name="dataSource" ref="dataSource"/>
  </bean>

  

4)配置Service层+Dao层的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--  配置Service对象  -->
 <bean id="roleService" class="com.xc.service.impl.RoleServiceImpl">
     <property name="roleDao" ref="roleDao"/>
 </bean>
 
 <!--  配置Dao对象  -->
 <bean id="roleDao" class="com.xc.dao.impl.RoleDaoImpl">
     <property name="jdbcTemplate" ref="jdbcTemplate"/>
 </bean>
 
 <bean id="userService" class="com.xc.service.impl.UserServiceImpl">
     <property name="userDao" ref="userDao"/>
     <property name="roleDao" ref="roleDao"/>
 </bean>
 
 <bean id="userDao" class="com.xc.dao.impl.UserDaoImpl">
     <property name="jdbcTemplate" ref="jdbcTemplate"/>
 </bean>

  

web层使用注解的方式配置映射和注入相应的Service类,而Service层和Dao层对象则是通过ApplicationContext.xml配置。

2. 角色列表的展示步骤分析

1)点击角色管理菜单发送请求到服务器端

1
2
3
<li><a
  href="${pageContext.request.contextPath}/role/list"> <br>  <i class="fa fa-circle-o"></i> 角色管理
</a></li>

  

该请求会通过MVC,扫描Controller下的/role/list,执行对应的业务方法。

然后由该业务方法返回的ViewName来显示页面,该业务方法返回的Model来返回要显示的数据。

2)创建RoleController和showList()方法

1
2
3
4
5
6
7
8
9
10
@RequestMapping("/list")
  public ModelAndView list(){
      ModelAndView modelAndView = new ModelAndView();
      List<Role> roleList = roleService.list();
      //设置模型
      modelAndView.addObject("roleList",roleList);
      //设置视图
      modelAndView.setViewName("role-list");
      return modelAndView;
  }

  

RoleController层都是/role子目录下的业务方法,该业务方法是/list。

该方法既要回传参数,又要跳转界面,所以返回ModelAndView对象。

该业务方法调用了roleService对象的list方法,所以要在类中配置一个RoleService服务类,并用注解自动注入,

由于类中仅有且仅会一个RoleService类,所以只用加注解@AutoWired。

1
2
@Autowired
  private RoleService roleService;

  

3)创建RoleService和showList()方法

到了Service层以及Dao层之后,一般采用接口+实现类的模式。

采用接口的原因,是为了让上层类不依赖于下层类。

如果下层类内部改变的话,不必修改上层类,这对更新和维护提供了方便。

还有一个我觉得方便的点,别的层的开发人员只需要对接口方法的注释进行查看,不用考虑方法的具体实现,可以直接拿来使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class RoleServiceImpl implements RoleService {
 
    private RoleDao roleDao;
 
    public void setRoleDao(RoleDao roleDao) {
        this.roleDao = roleDao;
    }
 
    public List<Role> list() {
 
        List<Role> roleList = roleDao.findAll();
        return roleList;
    }
}

  

这个服务方法构成简单,只要接收Dao层对角色的查询结果,所以仅仅在方法内调用了Dao层的findAll方法。

因为该类的配置已经在xml中配置,所以不需要加注解配置。

4)创建RoleDao和findAll()方法

接口和实现类的配置类似3)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class RoleDaoImpl implements RoleDao {
 
    private JdbcTemplate jdbcTemplate;
 
 
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
 
    public List<Role> findAll() {
 
        List<Role> roleList = jdbcTemplate.query("select * from sys_role", new BeanPropertyRowMapper<Role>(Role.class));
        return roleList;
    }
}

  

Dao层采用JDbc模板对数据库进行访问,方法中调用了query方法,通过映射注入Role实体类中然后放入集合,并以List<Role>接收。

具体用法在JdbcTemplate中已有说明。

5)使用JdbcTemplate完成查询操作

在4)中已有体现。

6)将查询数据存储到Model中

在2)中已有体现。

7)转发到role-list.jsp页面进行展示

在2)中已有体现。

 

3. 角色添加的步骤分析

1)点击列表页面新建按钮跳转到角色添加页面

1
2
3
<button type="button" class="btn btn-default" title="新建" onclick="location.href='${pageContext.request.contextPath}/pages/role-add.jsp'">
  <i class="fa fa-file-o"></i> 新建
</button>

  

通过location.href进行页面跳转。

2)输入角色信息,点击保存按钮,表单数据提交服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<form action="${pageContext.request.contextPath}/role/save"
  method="post">
  <!-- 正文区域 -->
  <section class="content"> <!--产品信息-->
 
  <div class="panel panel-default">
  <div class="panel-heading">角色信息</div>
  <div class="row data-type">
 
  <div class="col-md-2 title">角色名称</div>
  <div class="col-md-4 data">
  <input type="text" class="form-control" name="roleName"
    placeholder="角色名称" value="">
  </div>
  <div class="col-md-2 title">角色描述</div>
  <div class="col-md-4 data">
  <input type="text" class="form-control" name="roleDesc"
    placeholder="角色描述" value="">
  </div>
                                         
 </div>
</div>
  <!--订单信息/--> <!--工具栏-->
<div class="box-tools text-center">
  <button type="submit" class="btn bg-maroon">保存</button>
  <button type="button" class="btn bg-default"
  onclick="history.back(-1);">返回</button>
</div>
  <!--工具栏/--> </section>
  <!-- 正文区域 /--><br></form>

  

form表单以post形式提交至/role/save业务方法上,通过回传相应参数,有roleName,roleDesc。

3)编写RoleController的save()方法

类似之前业务的方法,映射一个/save地址。

1
2
3
4
5
@RequestMapping("/save")
 public String save(Role role){
     roleService.save(role);
     return "redirect:/role/list";
 }

  

此时的参数为实体类Role,类中的属性要与表单中的name属性一致,这样mvc才会将相应的属性一一对应注入。

返回必须是重定向的获取list的请求地址,如果跳过此步直接返回显示页面,页面中的数据会是空的。

4)编写RoleService的save()方法

1
2
3
public void save(Role role) {
       roleDao.save(role);
   }

  

5)编写RoleDao的save()方法

1
2
3
4
public void save(Role role) {
        jdbcTemplate.update("insert into sys_role values(?,?,?)",null,role.getRoleName(),role.getRoleDesc());
 
    }

6)使用JdbcTemplate保存Role数据到sys_role

已经在5)中有体现。

7)跳转返回角色列表页面

 

4.用户增加的步骤分析

步骤大体上与角色添加类似,但是有地方需要说明。

因为在添加用户的同时,需要指定用户的角色,而角色列表需要通过前端向后端请求获得,

并且添加用户的信息需要分成2部分保存。

1)用户本身的信息存放在sys_user表。

2)用户的角色信息存放在sys_user_role表。

此处有一个知识点,用户本身可以拥有多个角色身份,而一个角色身份也可以对应多个用户。

所以仅仅是用户表和角色表2个表并不能完全的符合这两者之间的关系。

一般这种多对多的关系需要第三张表,称为中间表。

本例中的中间表分为2列,一列是userId,代表用户的id,一列是roleId,代表角色的id。

每一条信息代表着,用户对应着某一角色。

 

 

 例如上图,用户1有2个角色,一个是角色1,一个是角色2。

4.1 加载添加用户的界面

controller层

1
2
3
4
5
6
7
8
@RequestMapping("/saveUI")
    public ModelAndView saveUI(){
        ModelAndView modelAndView = new ModelAndView();
        List<Role> roleList = roleService.list();
        modelAndView.addObject("roleList",roleList);
        modelAndView.setViewName("user-add");
        return modelAndView;
    }

  

查询角色的功能之前已经写过,所以直接复用就行,也是非常的方便。

其他层也是类似,不多赘述。

4.2 添加用户的功能

controller层

1
2
3
4
5
@RequestMapping("/save")
  public String save(User user,Long[] roleIds){
      userService.save(user,roleIds);
      return "redirect:/user/list";
  }

  

上文说到需要将信息分为2部分保存,参数User用来保存sys_user表的信息,roleIds数据用来保存sys_user_role表的信息。

Service层

1
2
3
4
5
6
public void save(User user, Long[] roleIds) {
        //第一步 向sys_user 表中存储数据
        long userId = userDao.save(user);
        //第二步 向sys_user_role 关系表中存储多条数据
        userDao.saveUserRoleRel(userId,roleIds);
    }

  

Dao层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public long save(final User user) {
 
        //创建PreparedStatementCreator
        PreparedStatementCreator creator = new PreparedStatementCreator() {
            public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
                //使用原始jdbc完成一个PreparedStatement的组建
                PreparedStatement preparedStatement = con.prepareStatement("insert into sys_user values(?,?,?,?,?)", PreparedStatement.RETURN_GENERATED_KEYS);
                preparedStatement.setObject(1,null);
                preparedStatement.setString(2,user.getUsername());
                preparedStatement.setString(3,user.getEmail());
                preparedStatement.setString(4,user.getPassword());
                preparedStatement.setString(5,user.getPhoneNum());
                return preparedStatement;
            }
        };
        //创建keyHolder
 
        GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();
 
        jdbcTemplate.update(creator,keyHolder);
 
        long userId = keyHolder.getKey().longValue();
        //jdbcTemplate.update("insert into sys_user values(?,?,?,?,?)",null,user.getUsername(),user.getEmail(),user.getPassword(),user.getPhoneNum());
        return userId;
    }

  

这边有一点需要说明,如果将update函数用sql语句来实现的话,传入的参数应该是user.getId(),但user中的id并不是前端传到后端去的,而是数据库表自增的id,所以并没有存放在实体类中。

jdbc有一个方法可以返回这个id值,第一个参数为PreparedStatementCreator对象,第二个为keyHolder对象,因为不常用加上现在有更好用的mybatis,所以只做练习,试一遍就好。

 

5 删除用户的功能

删除用户需要注意的点是,需要在请求地址上携带需要删除的用户id。

之前在进行列表展示的时候已经获取了用户的id,而且删除的按钮在同一循环里,所以要获取用户的id也非常的容易。

controller层

1
2
3
4
5
@RequestMapping("/del/{userId}")
  public String del(@PathVariable("userId") Long userId){
      userService.del(userId);
      return "redirect:/user/list";
  }

  

参数上的注解之前的文章也有说过,是获取请求地址中的变量。

 

Service层

1
2
3
4
5
6
public void del(Long userId) {
        //1、删除sys_user_role关系表
        userDao.delUserRoleRel(userId);
        //2、删除sys_user表
        userDao.del(userId);
    }

  

删除同样分为2部分进行删除,一个是删除从属表用户角色表,另一个是删除主表角色表。

 

Dao层

1
2
3
4
5
6
7
public void delUserRoleRel(Long userId) {
       jdbcTemplate.update("delete from sys_user_role where userId=?",userId);
   }
 
   public void del(Long userId) {
       jdbcTemplate.update("delete from sys_user where id=?",userId);
   }

  

posted @   小超和你  阅读(77)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
· 面试官:你是如何进行SQL调优的?
点击右上角即可分享
微信分享提示