SpringMVC
springmvc项目创建
1、使用maven创建web项目结构
2、补充更改结构

3、springmvc-config.xml
1)添加包扫描(context命名空间)
2)添加视图解析器
前缀后缀
| |
| <context:component-scan base-package="com.nfjh.springmvc.controller"/> |
| |
| <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> |
| <property name="prefix" value="/admin/"/> |
| <property name="suffix" value=".jsp"/> |
| </bean> |
| |
| |
4、更换新的web.xml文件
设置前置控制器DispatcherServlet
并在控制器中引入spring.xml的配置
| |
| <servlet> |
| <servlet-name>springmvc</servlet-name> |
| <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> |
| |
| <init-param> |
| <param-name>contextConfigLocation</param-name> |
| <param-value>classpath:springmvc-config.xml</param-value> |
| </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> |
| <url-pattern>*.action</url-pattern> |
| </servlet-mapping> |
5、index.jsp
<a href="${pageContext.request.contextPath}/hello.action">访问服务器</a>
6、在controller包下创建控制器类
| @Controller |
| public class UserController { |
| @RequestMapping("/hello.action") |
| public String sayHello(){ |
| return "main"; |
| } |
| } |
@RequestMapping
此注解就是来映射服务器访问的路径.
1)此注解可加在方法上,是为此方法注册一个可以访问的名称(路径)
| @RequestMapping("/demo.action") |
| public String demo(){ |
| System.out.println("服务器被访问到了......."); |
| return "main"; |
| } |
<a href="${pageContext.request.contextPath}/demo.action">访问服务器</a>
2)此注解可以加在类上,相当于是包名(虚拟路径),区分不同类中相同的action的名称
| @RequestMapping("/user.action") |
| public class DemoAction1 {..} |
<a href="${pageContext.request.contextPath}/user/demo.action">访问服务器</a>
3)此注解可区分get请求和post请求
| |
| @Controller |
| public class ReqAction { |
| @RequestMapping(value = "/req.action",method = RequestMethod.GET) |
| public String doGetTest(){ |
| System.out.println("我是处理get请求的........"); |
| return "main"; |
| } |
| @RequestMapping(value = "/req.action" ,method = RequestMethod.POST) |
| public String doPostTest(){ |
| System.out.println("我是处理post请求的........"); |
| return "main"; |
| } |
| } |
| |
| |
| |
| |
5中数据提交方式的优化

总结
| 1、表单name对应action方法形参 |
| 2、表单name对应实体类属性,action 形参类实体类 |
| 3、 仅限于超链接或地址拦提交数据,链接中的数据值以'/'分割 |
| action方法上的@RequestMapping(value="/{占位字符串1}/{占位字符串2}/submit.action") |
| 占位字符串对应action形参名,且需要使用@PathVariable解析 |
| 4、表单name与action方法形参名不对应时,在形参名前添加@RequestParam("表单name") |
| 5、action方法形参类型使用 (HttpServletRequest request),方法内部和以前一样 |
1)方法形参名
| <%--1、表单中name对应方法形参名--%> |
| <form action="${pageContext.request.contextPath}/submit1.action" method="post"> |
| <input type="text" name="student_name"/> |
| <input type="text" name="studentNo"/> |
| <input type="submit" value="submit"/> |
| </form> |
| |
| @RequestMapping(value={"/submit1.action"}) |
| public String getData1(String student_name, int studentNo){ |
| System.out.println(student_name + studentNo); |
| return "main"; |
| } |
2)封装实体类
| <%-- |
| 中文乱码问题: |
| 当前使用的是Tomcat10 ,post 和 get提交的中文乱码问题都已经被解决了 |
| Tomcat8之前的版本没有解决post乱码,但get请求的乱码问题可能已经解决 |
| |
| 所以对于低版本的Tomcat的post乱码需要解决 |
| |
| 实体类: |
| private String name; |
| private int age; |
| --%> |
| |
| <form action="${pageContext.request.contextPath}/submit2.action" method="post"> |
| <input type="text" name="name"/> |
| <input type="text" name="age"/> |
| <input type="submit" value="submit2"/> |
| </form> |
| @RequestMapping(value="/submit2.action") |
| public String getDataByPojo(Student student){ |
| System.out.println(student); |
| return "main"; |
| } |
3)动态占位符提交
| <a href="${pageContext.request.contextPath}/郭洪宇/20111022/submit3.action">submit3</a> |
| @RequestMapping(value = "/{name}/{no}/submit3.action") |
| public String getDataByPlaceholder( |
| //测试后发现 如果占位的字符串与形参不对应,会报500错误 |
| @PathVariable |
| String name, |
| @PathVariable |
| int no){ |
| System.out.println(name + no); |
| |
| return "main"; |
| } |
4) 映射名称不一致
| <form action="${pageContext.request.contextPath}/submit4.action" method="post"> |
| <input type="text" name="uname"/> |
| <input type="text" name="uage"/> |
| <input type="submit" value="submit4"/> |
| </form> |
| @RequestMapping(value = "/submit4.action") |
| public String getDataAndInconsistentMapping( |
| @RequestParam("uname") |
| String name, |
| @RequestParam("uage") |
| int age){ |
| System.out.println(name + age); |
| return "main"; |
| } |
5) HttpServletRequest
| <form action="${pageContext.request.contextPath}/submit5.action" method="post"> |
| <input type="text" name="name"/> |
| <input type="text" name="age"/> |
| <input type="submit" value="submit5"/> |
| </form> |
| @RequestMapping(value = "/submit5.action") |
| public String getDataByHttpServletRequest(HttpServletRequest request){ |
| String name = request.getParameter("name"); |
| int age = Integer.parseInt(request.getParameter("age")); |
| System.out.println(name + age); |
| return "main"; |
| } |
乱码问题
在web.xml文件中添加类CharacterEncoding类
| |
| |
| |
| |
| |
| |
| <filter> |
| <filter-name>encodingFilter</filter-name> |
| <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> |
| <init-param> |
| <param-name>encoding</param-name> |
| <param-value>UTF-8</param-value> |
| </init-param> |
| <init-param> |
| <param-name>forceRequestEncoding</param-name> |
| <param-value>true</param-value> |
| </init-param> |
| <init-param> |
| <param-name>forceResponseEncoding</param-name> |
| <param-value>true</param-value> |
| </init-param> |
| </filter> |
| <filter-mapping> |
| <filter-name>encodingFilter</filter-name> |
| <url-pattern>/*</url-pattern> |
| </filter-mapping> |
| |
ajax请求
pom.xml
| spring-webmvc |
| junit |
| jakarta.servlet-api |
| |
| <dependency> |
| <groupId>com.fasterxml.jackson.core</groupId> |
| <artifactId>jackson-databind</artifactId> |
| <version>2.14.1</version> |
| </dependency> |
index.jsp
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> |
| <html> |
| <head> |
| <title>Title</title> |
| <%--导入jQuery--%> |
| <script src="js/jquery-3.3.1.js"></script> |
| </head> |
| <body> |
| <a href="javascript:show()">点击显示学生信息</a> |
| <div id="mydiv"> |
| 等待响应..... |
| </div> |
| <script type="text/javascript"> |
| function show() { |
| $.ajax({ |
| url :"${pageContext.request.contextPath}/list.action", |
| type :"get", |
| dataType : "json", |
| success:function(responseList){ |
| let s = ""; |
| $.each(responseList,function (i,stuInfo){ |
| s+= stuInfo.name +"------"+ stuInfo.age +"</br>"; |
| }); |
| $("#mydiv").html(s); |
| } |
| }); |
| } |
| </script> |
| </body> |
| </html> |
| |
pojo
| private String name; |
| private int age; |
| ... |
action
| |
| |
| |
| |
| |
| |
| |
| @Controller |
| public class StudentListAction { |
| |
| @ResponseBody |
| @RequestMapping("/list.action") |
| public List<Student> classToJson(){ |
| List<Student> list = new ArrayList<>(); |
| list.add(new Student("小郭",22)); |
| list.add(new Student("小张",21)); |
| list.add(new Student("小刘",22)); |
| return list; |
| } |
| } |
web.xml → CharacterEncodingFilter 、DispatcherServlet
springmvc-config.xml
| |
| |
| |
| <context:component-scan base-package="com.springmvc.controller"/> |
| <mvc:annotation-driven/> |
跳转方式
前提回顾:
转发:携带的数据依旧存在,转发的过程发生在"服务器",由服务器转发到新的界面
重定向:全新的请求,重定向的过程发生在"客户端"
按照我的归类跳转方式为
- springmvc 默认返回值拼接转发
- forward: 转发action/转发页面
- redirect: 重定向action/重定向页面
- HttpServletRequest HttpServletResponse 转发
- HttpServletRequest HttpServletResponse 重定向
- 举例:
| @RequestMapping("/forward/test.action") |
| public String requestForwarding(){ |
| System.out.println("forward:转发开始"); |
| |
| return "forward:/ghy/other.action";\ |
| |
| |
| } |
| |
| @RequestMapping("/redirect/HttpServlet.action") |
| public void redirectHttpServlet(HttpServletRequest request, HttpServletResponse response) |
| throws ServletException, IOException { |
| System.out.println("HttpServlet重定向开始"); |
| response.sendRedirect(request.getContextPath() + "/admin/main.jsp"); |
| |
| } |
常用默认参数[可传递数据]
| HttpServletRequest |
| HttpServletResponse |
| Model |
| Map |
| ModelMap |
index.jsp
| <a href="${pageContext.request.contextPath}/data.action?haha=22">springmvc param</a> |
action:
| @Controller |
| public class DataParamAction { |
| @RequestMapping("/data.action") |
| public String forwardDataTest( |
| HttpServletRequest request, |
| HttpSession session, |
| Model model, |
| Map map, |
| ModelMap modelMap){ |
| |
| |
| Student stu = new Student("张三", 45); |
| request.setAttribute("requestStu",stu); |
| session.setAttribute("sessionStu",stu); |
| model.addAttribute("modelStu",stu); |
| map.put("map_stu",stu); |
| modelMap.addAttribute("modelMapStu",stu); |
| |
| return "forward:/data/data.jsp"; |
| } |
| } |
webapp/data/data.sp
| HttpServletRequest ${requestStu}<br> |
| HttpSession session${sessionStu}<br> |
| Model model${modelStu}<br> |
| Map map${map_stu}<br> |
| ModelMap modelMap${modelMapStu}<br> |
| |
| 错误写法:\${haha} ${haha}<br> |
| 正确写法:\${param.haha}${param.haha}<br> |
日期
单个日期
总结:@DateTimeFormat 加 mvc:annotation-driven/
springmvc-config.xml
| 添加mvc命名空间 |
| 开启注释解析器 |
| <mvc:annotation-driven/> |
index.jsp
| <form action="${pageContext.request.contextPath}/date.action" method="post"> |
| <input type="date" name="datePlaceholder1"/> |
| <input type="date" name="datePlaceholder2"/> |
| <input type="submit"/> |
| </form> |
| |
| SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
| |
| @RequestMapping("/date.action") |
| public String testDateParam( |
| @DateTimeFormat(pattern = "yyyy-MM-dd")Date datePlaceholder1, |
| @DateTimeFormat(pattern = "yyyy-MM-dd")Date datePlaceholder2){ |
| |
| |
| System.out.println("原始值:" + datePlaceholder1); |
| System.out.println("SimpleDateFormat: " + sdf.format(datePlaceholder1)); |
| System.out.println("原始值:" + datePlaceholder2); |
| System.out.println("SimpleDateFormat: " + sdf.format(datePlaceholder2)); |
| |
| return "main"; |
| } |
| |
| |
| |
| |
| |
| |
| |
多个日期,全局注解
使用@InitBinder注解,不需要添加mvc:annotation-driven/
| <form action="${pageContext.request.contextPath}/date2.action" method="post"> |
| <input type="date" name="datePlaceholder1"/> |
| <input type="date" name="datePlaceholder2"/> |
| <input type="submit"/> |
| </form> |
| @InitBinder |
| public void initBinderForDate(WebDataBinder webDataBinder){ |
| webDataBinder.registerCustomEditor( |
| Date.class,new CustomDateEditor(sdf,true) |
| ); |
| } |
| |
| @RequestMapping("/date2.action") |
| public String testDateParams(Date datePlaceholder1,Date datePlaceholder2){ |
| |
| |
| System.out.println("原始值:" + datePlaceholder1); |
| System.out.println("SimpleDateFormat: " + sdf.format(datePlaceholder1)); |
| System.out.println("原始值:" + datePlaceholder2); |
| System.out.println("SimpleDateFormat: " + sdf.format(datePlaceholder2)); |
| |
| return "main"; |
| } |
在jsp界面处理日期
1、添加依赖:[Tomcat 10版]
| |
| |
| <dependency> |
| <groupId>org.glassfish.web</groupId> |
| <artifactId>jakarta.servlet.jsp.jstl</artifactId> |
| <version>2.0.0</version> |
| </dependency> |
| |
| |
| |
| |
| |
[Tomcat 低版本]
| |
| |
| |
| |
| |
| |
| |
| |
| <dependency> |
| <groupId>jstl</groupId> |
| <artifactId>jstl</artifactId> |
| <version>1.2</version> |
| </dependency> |
| |
| |
| <dependency> |
| <groupId>javax.servlet</groupId> |
| <artifactId>jstl</artifactId> |
| <version>1.2</version> |
| </dependency> |
2、index.jsp
| <a href="${pageContext.request.contextPath}/date3.action">date数据在前端处理</a> |
3、模拟数据传给前端
| |
| @RequestMapping("/date3.action") |
| public String showDate(HttpServletRequest request) throws ParseException { |
| |
| |
| |
| |
| |
| Person jack = new Person("Jack", sdf.parse("2001-11-02")); |
| request.setAttribute("person",jack); |
| return "forward:/date/date.jsp"; |
| } |
4、数据处理 date.jsp
| 1- 导入格式化标签库 |
| <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> |
| 2- 使用 |
| <fmt:formatDate value="${person.birthday}" pattern="yyyy-MM-dd"/> |
| |
get、set方法上使用
| 可以在 |
| Person 中的birthday属性上添加 @DateTimeFormat(patter="yyyy-MM-dd")注解 |
| 或者在set方法上添加 |
| |
| 如果返回的是JSON格式数据在get方法上添加 |
| [具体内容看文档.doc] |
WEB-INF资源访问受限问题
举例:
webapp文件结构:
webapp
WEB-INF
jsp
hello.jsp
web.xml
index.jsp
| spring-config.xml: |
| |
| <context:component-scan base-package="com.nfjh.springmvc.controller"/> |
| |
| web.xml |
| |
| @Controller |
| public class UserController { |
| |
| @RequestMapping("/hello.action") |
| public String sayHello(){ |
| return "/WEB-INF/jsp/hello.jsp"; |
| |
| |
| } |
| } |
此目录下的动态资源,不可直接访问,只能通过请求转发的方式进行访问
| 访问路径: |
| http://localhost:8080/项目名/hello.action |
简单登录功能
结构:

| @Controller |
| public class LoginController { |
| |
| @RequestMapping("/loginAction") |
| public String toLogin(){ |
| return "login"; |
| } |
| |
| @RequestMapping("/loginCheck") |
| public String loginCheck(String name, String passwd, HttpServletRequest request){ |
| |
| |
| if (name.equals("hello")&&passwd.equals("world")){ |
| |
| return "hello"; |
| }else{ |
| |
| request.setAttribute("mgs","用户名或密码不正确!"); |
| return "login"; |
| } |
| |
| } |
| } |
| |
springmvc-config.xml
| |
| <context:component-scan base-package="com.nfjh.springmvc.controller"/> |
| |
| <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> |
| <property name="prefix" value="/WEB-INF/jsp/"/> |
| <property name="suffix" value=".jsp"/> |
| </bean> |
web.xml
| |
| 但是过滤器的过滤路径变成了'/' |
| <url-pattern>/</url-pattern> |
http://localhost:8080/springmvc_05_webInf_war/loginAction
拦截器

| SpringMVC的拦截器 |
| 针对请求和响应进行的额外的处理.在请求和响应的过程中添加预处理,后处理和最终处理. |
| |
| 拦截器执行的时机 |
| 1)preHandle():在请求被处理之前进行操作,预处理 |
| 2)postHandle():在请求被处理之后,但结果还没有渲染前进行操作,可以改变响应结果,后处理 |
| 3)afterCompletion:所有的请求响应结束后执行善后工作,清理对象,关闭资源 ,最终处理. |
| |
| 拦截器实现的两种方式 |
| 1)继承HandlerInterceptorAdapter的父类 |
| 2)实现HandlerInterceptor接口,实现的接口,推荐使用实现接口的方式 |
HandlerInterceptor实现三步
1、存储数据到session中
2、实现HandlerInterceptor接口
3、在springmvc-config.xml文件中注册拦截器
[springmvc_05_webInf]
| @Controller |
| public class LoginController { |
| |
| @RequestMapping("/loginAction") |
| public String toLogin(){ |
| return "login"; |
| } |
| |
| @RequestMapping("/loginCheck") |
| public String loginCheck(String name, String passwd, HttpServletRequest request){ |
| |
| |
| if (name!=null&&passwd!=null&& |
| name.equals("hello")&&passwd.equals("world")){ |
| |
| |
| request.getSession().setAttribute("name",name); |
| return "hello"; |
| }else{ |
| |
| request.setAttribute("mgs","用户名或密码不正确!"); |
| return "login"; |
| } |
| } |
| |
| @RequestMapping("/other") |
| public String otherPage(){ |
| return "other"; |
| } |
| } |
| |
| |
| |
| |
| public class LoginInterceptor implements HandlerInterceptor { |
| |
| @Override |
| public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) |
| throws Exception { |
| |
| |
| HttpSession session = request.getSession(); |
| Object name = session.getAttribute("name"); |
| if (name==null){ |
| request.setAttribute("mgs","用户未登录,请登录!!"); |
| request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response); |
| } |
| |
| return true; |
| } |
| } |
| |
| <mvc:interceptors> |
| <mvc:interceptor> |
| |
| <mvc:mapping path="/**"/> |
| |
| <mvc:exclude-mapping path="/loginAction"/> |
| <mvc:exclude-mapping path="/loginCheck"/> |
| |
| <bean class="com.nfjh.springmvc.interceptor.LoginInterceptor"/> |
| </mvc:interceptor> |
| </mvc:interceptors> |
不是,关于登录验证的不能拦截,首页展示不能拦截
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
· 面试官:你是如何进行SQL调优的?