一、回顾 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")@ResponseBodypublic 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 ejoin 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")@ResponseBodypublic 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")@ResponseBodypublic boolean delete(int id) {int i = empMapper.deleteByPrimaryKey(id);return i > 0;}
}