SpringMVC 进阶学习笔记
一、回顾 SpringMVC 基础
(一)框架作用与搭建流程
SpringMVC 主要用于处理客户请求、处理数据并响应客户。其搭建流程包括引入依赖(如 spring-webmvc)、编写配置文件(进行包扫描、开启注解驱动、静态资源放行、配置视图解析器)、注册 Servlet(DispatherServlet)以及编写 Controller 类的方法。
(二)参数接收方式
少量参数可直接使方法参数名与传递参数名一致;大量参数则可封装实体类,确保属性与传递参数名一致。同时,设置编码过滤器可解决中文乱码等问题。
二、深入学习 SpringMVC
(一)跳转控制
- 视图解析器的作用与跳过方式
视图解析器会按照配置将返回字符串解析为跳转路径。若不想经过视图解析器,可使用 redirect 和 forward 关键字。例如,在 Controller 方法中返回 "redirect:/main.jsp" 将直接重定向到指定页面,而 "forward:/main.jsp" 则使用转发跳转到指定路径,均无需视图解析器介入。
(二)数据传递给页面
- 保存到 request 的方式
- 使用 request 对象:在 Controller 方法中,可直接通过 request.setAttribute ("list", list) 将数据保存到 request 域中,然后在页面通过 EL 表达式获取。以下是一个简单示例:
@RequestMapping("/list")
public String list(HttpServletRequest request) {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
request.setAttribute("list", list);
return "List";
}
- 使用 Model 对象:SpringMVC 提供的 Model 对象默认保存周期与 request 等价。例如,在方法中通过 model.addAttribute ("list", list) 保存数据,同样可在页面获取。使用 Model 对象可降低与 Servlet API 的耦合度。
@RequestMapping("/list")
public String list(Model model) {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
model.addAttribute("list", list);
return "List";
}
- 保存到 session 的方式
- 直接使用 session 对象:如在登录方法中,通过 session.setAttribute ("userinfo", userinfo) 将用户信息保存到 session 中,以便在多个请求间共享数据。
@RequestMapping("/login")
public String login(HttpSession session) {
List<String> list = new ArrayList<>();
list.add("张三1");
list.add("李四2");
list.add("王五3");
session.setAttribute("list", list);
return "list";
}
- 借助 Model 对象:Model 对象也可用于将数据保存到 session,但需注意其默认有效期等价于 request。若要设置为 session 范围,可结合 @SessionAttributes 注解,如 @SessionAttributes ({"list"}),使特定键值的数据在 session 中有效。
@Controller
@RequestMapping("/user")
@SessionAttributes({"list"})
public class UserController {
@RequestMapping("/Login")
public String Login(Model model) {
List<String> list = new ArrayList<>();
list.add("张三1");
list.add("李四2");
list.add("王五3");
model.addAttribute("list", list);
model.addAttribute("list2", list);
return "list";
}
}
(三)返回 JSON 数据
- 适用场景与传统方式
在处理 ajax 异步请求时,常需要返回 JSON 数据。传统方式需使用工具(如 fastjson)将 Java 对象转换为 JSON 对象,再通过 out.print (json 字符串) 输出并关闭流。 - SpringMVC 简化操作
引入 jackson 依赖后,在方法上使用 @ResponseBody 注解,SpringMVC 会自动将方法返回的对象转换为 JSON 格式。例如,在返回员工列表的方法中,使用 @ResponseBody,方法返回的 List<Emp>对象将被转换为 JSON 数据返回给前端。
@Controller
public class AjaxController {
@RequestMapping("/List")
@ResponseBody
public List<User> list() {
List<User> list = new ArrayList<>();
list.add(new User(1, 23, "张三", "男", "打游戏", "12345678901", new Date()));
list.add(new User(2, 23, "张三2", "男", "打游戏2", "12345678901", new Date()));
list.add(new User(2, 23, "张三3", "男", "打游戏2", "12345678901", new Date()));
return list;
}
}
(四)拦截器
拦截器可在请求处理前后进行拦截操作,如进行权限验证、日志记录等。通过实现 HandlerInterceptor 接口并重写 preHandle、postHandle 和 afterCompletion 方法来定义拦截逻辑,然后在 SpringMVC 配置文件中注册拦截器。
(五)全局异常处理
用于统一处理应用程序中的异常,避免异常直接暴露给用户。可通过实现 HandlerExceptionResolver 接口或使用 @ControllerAdvice 注解结合 @ExceptionHandler 注解来定义全局异常处理方法,使异常处理更加优雅和统一。
(六)文件上传
SpringMVC 提供了文件上传的支持,需在配置文件中配置文件上传解析器(如 CommonsMultipartResolver),并在 Controller 方法中使用 MultipartFile 类型的参数接收上传文件,然后进行相应的保存或处理操作。
三、综合案例实践
(一)工程搭建步骤
- 创建 maven 的 web 工程,引入相关依赖,包括 mybatis、mysql、springmvc、lombok、servlet、jackson 等。
- 定义实体类、dao 接口及映射文件,可借助插件提高效率。
- 配置 spring 和 mybatis 配置文件,如设置包扫描、开启注解驱动、配置数据源等。
- 注册公共 servlet(DispatherServlet),指定配置文件位置。
- 编写编码过滤器,确保请求和响应的字符编码一致。
- 创建登录页面,使用 ajax 提交登录请求。
(二)登录业务实现
- 在 maper 接口中定义根据账号和密码查询用户的方法。
// UserinfoMapper.java
public interface UserinfoMapper {
Userinfo selectByNameAndPwd(@Param("name") String name, @Param("pwd") String pwd);
}
- 在映射文件中编写对应的 SQL 查询语句。
<!-- UserinfoMapper.xml -->
<select id="selectByNameAndPwd" resultMap="BaseResultMap">
select * from tbl_userinfo where name=#{name} and password=#{pwd}
</select>
- 在 Controller 中注入 maper 接口,在登录方法中调用查询方法,验证用户信息。若登录成功,将用户信息保存到 session 中,并返回 true;否则返回 false。前端通过 ajax 接收返回结果,根据结果进行页面跳转或提示错误信息。
@Controller
@RequestMapping("/user")
public class UserController {
private UserinfoMapper userinfoMapper;
private SqlSession sqlSession;
public UserController() throws Exception {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
sqlSession = sqlSessionFactory.openSession();
userinfoMapper = sqlSession.getMapper(UserinfoMapper.class);
}
@RequestMapping("/login")
@ResponseBody
public boolean login(String name, String pwd, HttpSession session) {
Userinfo userinfo = userinfoMapper.selectByNameAndPwd(name, pwd);
if (userinfo!= null) {
session.setAttribute("userinfo", userinfo);
return true;
} else {
return false;
}
}
}
(三)主页员工信息展示
- 在 dao 接口中定义查询所有员工信息的方法。
// EmpMapper.java
public interface EmpMapper {
List<Emp> selectAll();
}
- 在映射文件中编写复杂的 SQL 查询语句,通过关联查询获取员工及其所属部门信息,并使用 resultMap 进行结果映射。
<!-- EmpMapper.xml -->
<resultMap id="BaseResultMap" type="com.lyk.entity.Emp">
<id property="empId" column="emp_id" jdbcType="INTEGER"/>
<result property="empName" column="emp_name" jdbcType="VARCHAR"/>
<result property="empJob" column="emp_job" jdbcType="VARCHAR"/>
<result property="empSalary" column="emp_salary" jdbcType="DECIMAL"/>
<result property="did" column="did" jdbcType="INTEGER"/>
<association property="dept" javaType="com.aaa.entity.Dept">
<id property="deptId" column="dept_id" jdbcType="INTEGER"/>
<result property="deptName" column="dept_name" jdbcType="VARCHAR"/>
<result property="deptLoc" column="dept_loc" jdbcType="VARCHAR"/>
</association>
</resultMap>
<select id="selectAll" resultMap="BaseResultMap">
select *
from tbl_emp e
join tbl_dept d on e.did = d.dept_id
</select>
- 在 Controller 中调用 dao 方法获取员工列表,使用 @ResponseBody 将列表转换为 JSON 数据返回。前端通过 ajax 请求获取数据,使用 JavaScript 动态生成表格展示员工信息,包括编号、姓名、职位、薪资、部门名等,并为删除和修改操作添加相应的事件处理。
@Controller
@RequestMapping("/emp")
public class EmpController {
private EmpMapper empMapper;
private SqlSession sqlSession;
public EmpController() throws Exception {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
sqlSession = sqlSessionFactory.openSession();
empMapper = sqlSession.getMapper(EmpMapper.class);
}
@RequestMapping("/list")
@ResponseBody
public List<Emp> list() {
List<Emp> emps = empMapper.selectAll();
return emps;
}
}
(四)删除功能实现
在 Controller 中定义删除方法,接收员工 id 参数,调用 dao 的删除方法,根据删除结果返回 true 或 false。前端在点击删除按钮时,通过 ajax 发送删除请求,根据返回结果提示用户操作是否成功,并刷新员工列表。
@Controller
@RequestMapping("/emp")
public class EmpController {
private EmpMapper empMapper;
private SqlSession sqlSession;
public EmpController() throws Exception {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
sqlSession = sqlSessionFactory.openSession();
empMapper = sqlSession.getMapper(EmpMapper.class);
}
@RequestMapping("/delete")
@ResponseBody
public boolean delete(int id) {
int i = empMapper.deleteByPrimaryKey(id);
return i > 0;
}
}