Spring MVC 是 Spring 框架中的一个模块,用于构建基于 MVC(Model-View-Controller)设计模式的 Web 应用程序。它分离了应用程序的业务逻辑、用户界面和用户输入,使开发更加模块化和易于维护。
<dependency>
<groupId>jakarta.servletgroupId>
<artifactId>jakarta.servlet-apiartifactId>
<version>6.0.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>jakarta.servlet.jsp.jstlgroupId>
<artifactId>jakarta.servlet.jsp.jstl-apiartifactId>
<version>3.0.2version>
dependency>
<dependency>
<groupId>org.glassfish.webgroupId>
<artifactId>jakarta.servlet.jsp.jstlartifactId>
<version>3.0.1version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>6.2.3version>
dependency>
package com.myLearning;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");
if(method.equals("add")) {
req.getSession().setAttribute("msg", "执行add方法");
}else{
req.getSession().setAttribute("msg","执行了不知所谓的方法");
}
// 转发请求
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
<html>
<head>
<title>测试title>
head>
<body>
${msg}
body>
html>
<html>
<head>
<title>hellotitle>
head>
<body>
<form action="/test" method="post">
method:<input type="text" name="method"/>
<input type="button" value="submit" onclick="submit()">
form>
body>
html>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<session-config>
<session-timeout>15session-timeout>
session-config>
<welcome-file-list>
<welcome-file>hello.jspwelcome-file>
welcome-file-list>
<servlet>
<servlet-name>testServletservlet-name>
<servlet-class>com.myLearning.HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>testServletservlet-name>
<url-pattern>/testurl-pattern>
servlet-mapping>
web-app>
用户请求 -> DispatcherServlet -> HandlerMapping -> HandlerExecutionChain -> HandlerAdapter -> Controller -> ModelAndView -> ViewResolver -> View -> 渲染响应 -> 返回用户
用户发送请求
用户通过浏览器发起 HTTP 请求,请求被发送到 Spring MVC 的前端控制器 DispatcherServlet
。
DispatcherServlet 接收请求
DispatcherServlet
是 Spring MVC 的核心组件,负责接收所有的请求。
HandlerMapping 查找处理器
DispatcherServlet
调用 HandlerMapping
,根据请求的 URL 查找对应的处理器(Controller
或 Handler
)。
HandlerMapping
返回一个 HandlerExecutionChain
,包含处理器和可能的拦截器。HandlerAdapter 调用处理器
DispatcherServlet
通过 HandlerAdapter
调用处理器(Controller
或 Handler
)。HandlerAdapter
的作用是适配不同类型的处理器(如基于注解的 @Controller
、基于接口的 Controller
实现类等)。HandlerAdapter
实现包括 RequestMappingHandlerAdapter
(用于处理 @Controller
和 @RequestMapping
注解)。处理器执行业务逻辑
Controller
)执行业务逻辑,可能会调用 Service 层或 DAO 层。ModelAndView
对象,包含模型数据(Model)和视图名称(View)。处理拦截器(可选)
如果配置了拦截器(HandlerInterceptor
),在处理器执行前后会调用拦截器的 preHandle
和 postHandle
方法。
视图解析(ViewResolver)
DispatcherServlet
调用 ViewResolver
,根据 ModelAndView
中的视图名称解析出具体的视图对象(如 JSP、Thymeleaf 等)。
渲染视图(View)
DispatcherServlet
将模型数据传递给视图,视图根据模型数据渲染生成最终的 HTML 内容。
返回响应
渲染后的视图内容通过 DispatcherServlet
返回给客户端(浏览器),完成整个请求-响应流程。
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<session-config>
<session-timeout>15session-timeout>
session-config>
<welcome-file-list>
<welcome-file>hello.jspwelcome-file>
welcome-file-list>
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc-servlet.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
package com.myLearning.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
//注意:这里我们先导入Controller接口
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//ModelAndView 模型和视图
ModelAndView mv = new ModelAndView();
//封装对象,放在ModelAndView中。Model
mv.addObject("msg","HelloSpringMVC!");
//封装要跳转的视图,放在ModelAndView中
mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
return mv;
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
bean>
<bean id="/hello" class="com.myLearning.controller.HelloController"/>
beans>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Hello
${msg}
<build>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
resources>
build>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc-servlet.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.myLearning.controller"/>
<mvc:default-servlet-handler />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
bean>
beans>
在其中我们需要使用@Controller注解来标识这个类是一个controller,并且使用@RequestMapping注解来指定这个controller的访问路径
package com.myLearning.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/HelloController")
public class HelloController {
//真实访问地址 : 项目名/HelloController/hello
@RequestMapping("/hello")
public String sayHello(Model model){
//向模型中添加属性msg与值,可以在JSP页面中取出并渲染
model.addAttribute("msg","hello,SpringMVC");
//web-inf/jsp/hello.jsp
return "hello";
}
}
经过上面两种方式的程序编写,我们现在总结一下Controller的两种编写方式:
1.实现Controller接口
2.使用注解@Controller标识,在类中定义处理请求的方法,并使用@RequestMapping等注解来映射请求的URL
实现Controller接口,需要重写handleRequest方法,该方法返回一个ModelAndView对象。
package com.myLearning.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
//向模型中添加属性msg与值,可以在JSP页面中取出并渲染
mv.addObject("msg","hello,SpringMVC");
//web-inf/jsp/hello.jsp
mv.setViewName("hello");
return mv;
}
}
编写完后,我们还需要在springmvc.xml中配置我们的Controller
<bean name="/hello" class="com.myLearning.controller.HelloController"/>
使用@Controller注解标识该类为处理请求的Controller,通过@RequestMapping注解设置请求的路径。
package com.myLearning.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/HelloController")
public class HelloController {
//真实访问地址 : 项目名/HelloController/hello
@RequestMapping("/hello")
public String sayHello(Model model){
//向模型中添加属性msg与值,可以在JSP页面中取出并渲染
model.addAttribute("msg","hello,SpringMVC");
//web-inf/jsp/hello.jsp
return "hello";
}
}
然后,我们需要在springmvc.xml中配置扫描包即可
<context:component-scan base-package="com.myLearning.controller"/>
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
资源:互联网所有的事物都可以抽象为资源
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
分别对应 添加、删除、修改、查询。
通过不同的参数来实现不同的效果!方法单一,都是get。
http://127.0.0.1/item/queryItem.action?id=1 查询,GET
http://127.0.0.1/item/saveItem.action 新增,POST
http://127.0.0.1/item/1 查询,GET
http://127.0.0.1/item 新增,POST
那么我们如何获取restful风格中传递的参数呢?请看下面的示例:
我们先编写一个/Web-INF/jsp/test1.jsp页面用于测试:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>test1title>
head>
<body>
计算结果为:${rst}
${msg}
body>
html>
然后我们创建一个新的controller类,在这个类中,我们指明访问路径,以及路径中的参数名用于获取从路径中传递的参数:
package com.myLearning.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class Controller2 {
// 在定义时,我们可以指定对应位置映射的参数名
@RequestMapping("/t1/{a}/{b}")
// 我们可以在参数中指明我们将要从路径的哪个参数名中获取对应参数
public String test1(@PathVariable("a") int a, @PathVariable("b") int b, Model model) {
model.addAttribute("rst",a + b);
model.addAttribute("msg", "Hello World");
return "test1";
}
}
除了我们可以指定参数之外,我们还可以设置方法对应的请求类型,比如我们只希望这个方法处理get请求,那么我们可以这样写:
@RequestMapping(value = "/t1/{a}/{b}", method = RequestMethod.GET)
同理,可以设置method为POST,PUT,DELETE等,用于处理不同类型的请求。
还有另一种形式可以指定请求的类型:
@GetMapping("/t1/{a}/{b}")
这种形式是用于指定处理Get类型请求的的简写形式,类似的表达还有@PostMapping, @PutMapping, @DeleteMapping
在一般情况下,我们让SpringMVC通过我们返回的视图名称,以及经过视图解析器处理后,得到我们最后要跳转的页,如:
在SpringMVC配置文件中设置视图解析器:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
bean>
然后我们就可以在方法中返回视图名称,交由视图解析器处理,如:
@RequestMapping("/t1/{a}/{b}")
public String test1(@PathVariable("a") int a, @PathVariable("b") int b, Model model) {
model.addAttribute("rst",a + b);
model.addAttribute("msg", "Hello World");
return "test1";
}
我们也可以在方法中获取Servlet 中使用的变量,并使用其API
完成转发
@GetMapping("/t1/{a}/{b}")
public void test1(@PathVariable("a") int a, @PathVariable("b") int b, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, ServletException, IOException {
request.setAttribute("rst",a + b);
request.setAttribute("msg", "Hello World!!!");
// 使用Servlet API进行转发
request.getRequestDispatcher("/WEB-INF/jsp/test1.jsp").forward(request, response);
}
完成重定向
@GetMapping("/t1/{a}/{b}")
public void test1(@PathVariable("a") int a, @PathVariable("b") int b, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, ServletException, IOException {
request.setAttribute("rst",a + b);
request.setAttribute("msg", "Hello World!!!");
// 使用Servlet API进行重定向
response.sendRedirect(request.getContextPath() + "/hello.jsp");
}
完成转发
@GetMapping("/t1/{a}/{b}")
public String test2(@PathVariable("a") int a, @PathVariable("b") int b,Model model) {
// 无视图解析器完成转发
return "forward:/hello.jsp";
}
完成重定向
@GetMapping("/t1/{a}/{b}")
public String test2(@PathVariable("a") int a, @PathVariable("b") int b,Model model) {
// 无视图解析器完成重定向
return "redirect:/hello.jsp";
}
完成重定向
@GetMapping("/t1/{a}/{b}")
public String test2(@PathVariable("a") int a, @PathVariable("b") int b,Model model) {
// 有视图解析器完成重定向
return "redirect:/hello.jsp";
}
完成转发
@GetMapping("/t1/{a}/{b}")
public String test2(@PathVariable("a") int a, @PathVariable("b") int b,Model model) {
// 有视图解析器完成转发
return "hello";
}
我们通常会在请求中附带额外的参数数据,如:http://localhost:8080/hello?name=张三&age=18,除此之外还会有类似username,password等数据,我们如何获取这些数据呢?
我们可以使用@RequestParam注解来获取传递的参数
假设我们有一个请求,请求地址为:http://localhost:8080/test1?name=jack
我们可以通过如下方式获取到name的值:
@RequestMapping("/test1")
public String test3(@RequestParam("name") String name, Model model) {
System.out.println(name);
return "hello";
}
我们可以直接将实体类对象作为方法参数,SpringMVC会自动将请求中的参数封装到实体类对象中
假设我们有一个实体类User,如下:
package com.myLearning.pojo;
import org.apache.ibatis.type.Alias;
import java.io.Serializable;
@Alias("user")
public class User implements Serializable {
private int id;
private String name;
private String pwd;
public User() {
}
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
并且假设我们的url为:http://localhost:8080/test1?name=jack&pwd=123456&id=1
我们可以通过以下方式获取参数:
@RequestMapping("/test1")
public String test3(User user, Model model) {
System.out.println(user);
return "hello";
}
这二者都是用于向前端视图页面传递数据的,ModelMap继承了LinkedHashMap,具有LinkedHashMap的所有方法,而Model是精简版,我们大部分时间使用Model即可。
如果前端传递的数据中包括中文,如: 张三、李四、利姆露等,那么我们在处理的时候可能会出现乱码问题,这个时候,我们可以通过以下方式解决:
在web.xml中添加以下代码:
<filter>
<filter-name>encodingfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>utf-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
在tomcat的conf/server.xml中设置以下代码:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8"/>
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript的一个子集,但独立于编程语言,广泛用于Web应用中的数据交换。其本质其实就是一个字符串,只不过这个字符串的格式比较特殊,符合一定的规则。
轻量级:JSON格式简洁,数据量小,适合网络传输。
易读性:结构清晰,便于人类阅读和理解。
独立性:不依赖特定语言,几乎所有编程语言都支持JSON。
数据结构:支持对象(键值对)和数组(有序列表)两种主要结构。
JSON和JavaScript对象之间的转换是JSON数据在Web应用中常用的操作。在JavaScript中,可以使用内置的JSON对象来进行转换。
使用JSON.parse()
方法可以将JSON字符串转换为JavaScript对象。
var jsonString = '{"name":"John", "age":30, "city":"New York"}';
var jsonObject = JSON.parse(jsonString);
console.log(jsonObject.name); // 输出 "John"
使用JSON.stringify()
方法可以将JavaScript对象转换为JSON字符串。
javascript
var jsonObject = {name: "John", age: 30, city: "New York"};
var jsonString = JSON.stringify(jsonObject);
console.log(jsonString); // 输出 '{"name":"John","age":30,"city":"New York"}'
首先我们需要添加Jackson的依赖:
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.18.3version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-coreartifactId>
<version>2.18.3version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-annotationsartifactId>
<version>2.18.3version>
dependency>
然后我们编写一个controller类,用于返回JSON数据:
package com.myLearning.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.myLearning.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class Controller1 {
@RequestMapping("/json1")
@ResponseBody//@ResponseBody注解,指定返回的结果不走视图解析器,而是直接作字符串返回
public String json1() throws JsonProcessingException {
//创建一个jackson的对象映射器,用来解析数据
ObjectMapper mapper = new ObjectMapper();
//创建一个对象
User user = new User(1,"利姆露","666666");
//将我们的对象解析成为json格式
String str = mapper.writeValueAsString(user);
//由于@ResponseBody注解,这里会将str转成json格式返回;十分方便
return str;
}
}
测试时,我们会发现显示有乱码问题,此时我们可以通过设置@RequestMaping的produces属性来实现:
package com.myLearning.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.myLearning.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class Controller1 {
// 我们设置了其produces的属性
@RequestMapping(value = "/json1",produces = "application/json;charset=utf-8")
@ResponseBody//@ResponseBody注解,指定返回的结果不走视图解析器,而是直接作字符串返回
public String json1() throws JsonProcessingException {
//创建一个jackson的对象映射器,用来解析数据
ObjectMapper mapper = new ObjectMapper();
//创建一个对象
User user = new User(1,"利姆露","666666");
//将我们的对象解析成为json格式
String str = mapper.writeValueAsString(user);
//由于@ResponseBody注解,这里会将str转成json格式返回;十分方便
return str;
}
}
除此之外,我们还可以在springmvc.xml中配置消息转换器,也可以解决乱码问题:
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
bean>
property>
bean>
mvc:message-converters>
mvc:annotation-driven>
现在我们已经可以成功解决乱码问题了,但是现在我们每设置一个方法返回JSON字符串,我们都需要添加@ResponseBody注解,这样显然是不方便的,所以我们可以直接在类的上方添加@RestController注解,这样就可以省略掉每个方法的@ResponseBody注解了。
package com.myLearning.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.myLearning.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Controller1 {
// 我们设置了其produces的属性
@RequestMapping(value = "/json1")
public String json1() throws JsonProcessingException {
//创建一个jackson的对象映射器,用来解析数据
ObjectMapper mapper = new ObjectMapper();
//创建一个对象
User user = new User(1,"利姆露","666666");
//将我们的对象解析成为json格式
String str = mapper.writeValueAsString(user);
//由于@ResponseBody注解,这里会将str转成json格式返回;十分方便
return str;
}
}
如果我们直接使用ObjectMapper
来输出时间的话,输出的格式默认为时间戳,即1970年到现在的毫秒数,这可能不是我们想要的,所以我们需要自定义时间格式。
@RequestMapping("/json2")
public String json2() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//不使用时间戳的方式
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//自定义日期格式对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//指定日期格式
mapper.setDateFormat(sdf);
Date date = new Date();
String str = mapper.writeValueAsString(date);
return str;
}
我们可以发现,每次使用ObjectMapper
时都需要进行一些重复的操作,所以我们可以将其封装成一个工具类,方便我们使用。
package com.myLearning.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.text.SimpleDateFormat;
public class JsonUtils {
public static String getJson(Object object) {
return getJson(object,"yyyy-MM-dd HH:mm:ss");
}
public static String getJson(Object object,String dateFormat) {
ObjectMapper mapper = new ObjectMapper();
//不使用时间差的方式
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
//自定义日期格式对象
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
//指定日期格式
mapper.setDateFormat(sdf);
try {
return mapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
FastJSON 是阿里巴巴开源的一个高性能的 JSON 库,用于 Java 对象与 JSON 数据之间的序列化(将 Java 对象转换为 JSON 字符串)和反序列化(将 JSON 字符串转换为 Java 对象)。它是目前 Java 生态中性能最好的 JSON 库之一,广泛应用于各种 Java 项目中。
为了使用fastjson,需要在pom.xml文件中添加以下依赖:
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>2.0.56version>
dependency>
简单使用:
@RequestMapping("/json3")
public String json3() throws JsonProcessingException {
// 创建一个 User 对象
User user = new User(1, "利姆露", "123456233333333333");
// 序列化:将 User 对象转换为 JSON 字符串
String jsonString = JSON.toJSONString(user);
System.out.println("序列化结果:" + jsonString);
// 反序列化:将 JSON 字符串转换为 User 对象
User parsedUser = JSON.parseObject(jsonString, User.class);
System.out.println("反序列化结果:" + parsedUser);
return jsonString;
}
create database `ssmbuild`;
use `ssmbuild`;
create table `books`(
`bookID` int(10) not null auto_increment comment 'id',
`bookName` varchar(100) not null comment '书名',
`bookCounts` int(10) not null comment '数量',
`detail` varchar(255) not null comment '描述',
key `bookID` (`bookID`)
)ENGINE=InnoDB default charset=utf8;
insert into `books` (`bookID`,`bookName`,`bookCounts`,`detail`) VALUES
(1,'红楼梦',20,'理想的破灭'),
(2,'水浒传',30,'现实主义悲剧'),
(3,'c primer plus',40,'c 语言基础入门教程');
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.10version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.33version>
dependency>
<dependency>
<groupId>org.junit.jupitergroupId>
<artifactId>junit-jupiter-apiartifactId>
<version>5.10.0version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.junit.jupitergroupId>
<artifactId>junit-jupiter-engineartifactId>
<version>5.10.0version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-coreartifactId>
<version>2.20.0version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-apiartifactId>
<version>2.20.0version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.30version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>6.2.3version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>6.2.3version>
dependency>
<dependency>
<groupId>javax.annotationgroupId>
<artifactId>javax.annotation-apiartifactId>
<version>1.3.2version>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.5version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>3.0.4version>
dependency>
<dependency>
<groupId>jakarta.servletgroupId>
<artifactId>jakarta.servlet-apiartifactId>
<version>6.0.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>jakarta.servlet.jsp.jstlgroupId>
<artifactId>jakarta.servlet.jsp.jstl-apiartifactId>
<version>3.0.2version>
dependency>
<dependency>
<groupId>org.glassfish.webgroupId>
<artifactId>jakarta.servlet.jsp.jstlartifactId>
<version>3.0.1version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.18.3version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-coreartifactId>
<version>2.18.3version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-annotationsartifactId>
<version>2.18.3version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>2.0.56version>
dependency>
<dependency>
<groupId>com.mchangegroupId>
<artifactId>c3p0artifactId>
<version>0.9.5.4version>
dependency>
dependencies>
在pom.xml中配置resources,防止资源导出时的问题
<build>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>truefiltering>
resource>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>truefiltering>
resource>
resources>
build>
需要的软件包有:controller、service、dao、pojo
需要创建的资源配置文件:
mybatis-config.xml
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.myLearning.pojo"/>
typeAliases>
configuration>
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
beans>
database.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=123456
package com.myLearning.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
private int bookID;
private String bookName;
private int bookCounts;
private String detail;
}
package com.myLearning.dao;
import com.myLearning.pojo.Book;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface BookMapper {
// 添加一本书
int addBook(Book book);
// 删除一本书
int deleteBook(Book book);
// 修改一本书
int updateBook(Book book);
// 查询所有书
List<Book> getAllBooks();
// 查询包含关键字的书
List<Book> getBookByStr(@Param("str") String str);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.myLearning.dao.BookMapper">
<insert id="addBook" parameterType="book">
insert into books(`bookName`,`bookCounts`,`detail`) values
(#{bookName},#{bookCounts},#{detail});
insert>
<delete id="deleteBook" parameterType="book">
delete
from books
where `bookID` = #{bookID};
delete>
<update id="updateBook" parameterType="book">
update books
set `bookName` = #{bookName},
`bookCounts` = #{bookCounts},
`detail` = #{detail}
where `bookID` = #{bookID};
update>
<select id="getAllBooks" resultType="book">
select * from books;
select>
<select id="getBookByStr" parameterType="String" resultType="book">
select * from books where
`bookName` like concat('%',#{str},'%')
select>
mapper>
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
settings>
<typeAliases>
<package name="com.myLearning.pojo"/>
typeAliases>
<mappers>
<mapper class="com.myLearning.dao.BookMapper"/>
mappers>
configuration>
package com.myLearning.service;
import com.myLearning.pojo.Book;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface BookService {
// 添加一本书
int addBook(Book book);
// 删除一本书
int deleteBook(Book book);
// 修改一本书
int updateBook(Book book);
// 查询所有书
List<Book> getAllBooks();
// 查询包含关键字的书
List<Book> getBookByStr( String str);
}
package com.myLearning.service;
import com.myLearning.dao.BookMapper;
import com.myLearning.pojo.Book;
import java.util.List;
public class BookServiceImpl implements BookService {
private BookMapper bookMapper;
public BookMapper getBookMapper() {
return bookMapper;
}
public void setBookMapper(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}
@Override
public int addBook(Book book) {
return bookMapper.addBook(book);
}
@Override
public int deleteBook(Book book) {
return bookMapper.deleteBook(book);
}
@Override
public int updateBook(Book book) {
return bookMapper.updateBook(book);
}
@Override
public List<Book> getAllBooks() {
return bookMapper.getAllBooks();
}
@Override
public List<Book> getBookByStr(String str) {
return bookMapper.getBookByStr(str);
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:property-placeholder location="classpath:database.properties"/>
<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}"/>
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="10"/>
<property name="autoCommitOnClose" value="false"/>
<property name="checkoutTimeout" value="10000"/>
<property name="acquireRetryAttempts" value="2"/>
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<property name="basePackage" value="com.myLearning.dao"/>
bean>
beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.myLearning.service"/>
<context:annotation-config/>
<bean id="bookServiceImpl" class="com.myLearning.service.BookServiceImpl">
<property name="bookMapper" ref="bookMapper"/>
bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.myLearning.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
aop:config>
beans>
同时需要在项目结构中创建一个spring的子模块,并在其中添加我们已经创建的三个spring配置文件,applicationContext.xml、spring-mvc.xml、spring-service.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
<context:component-scan base-package="com.myLearning.controller"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
bean>
beans>
在applicationContext.xml中导入这个配置文件
<import resource="classpath:spring-mvc.xml"/>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:applicationContext.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
<filter>
<filter-name>encodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>utf-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<session-config>
<session-timeout>15session-timeout>
session-config>
web-app>
同时在/WEB-INF中创建jsp文件夹
现在我们已经完成了ssm的框架整合,接着我们可以为我们的网站添加功能了,首先我们需要创建一个BookController.java
package com.myLearning.controller;
import com.myLearning.pojo.Book;
import com.myLearning.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("/book")
public class BookController {
@Autowired
@Qualifier("bookServiceImpl")
private BookService bookService;
@RequestMapping("/getAllBooks")
public String getAllBooks(Model model) {
List<Book> books = bookService.getAllBooks();
model.addAttribute("books", books);
return "getAllBooks";
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>主页title>
<style>
a{
text-decoration: none;
color: cornflowerblue;
font-size: 20px;
}
h3{
width: 180px;
height: 60px;
margin: 100px auto;
text-align: center;
line-height: 60px;
background: ghostwhite;
}
style>
head>
<body>
<h3>
<a href="${pageContext.request.contextPath}/book/getAllBooks">点击进入书籍页面a>
h3>
body>
html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>书籍展示页面title>
<%-- 使用cdn引入 BootStrap 用于美化界面--%>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>书籍列表small>
h1>
div>
div>
div>
div>
<div class="row clearfix">
<div class="col-md-12 column">
<table class="table table-hover table-striped">
<thead>
<tr>
<th>书籍编号th>
<th>书籍名称th>
<th>书籍数量th>
<th>书籍详情th>
tr>
thead>
<tbody>
<c:forEach var="book" items="${books}">
<tr>
<td>${book.bookID}td>
<td>${book.bookName}td>
<td>${book.bookCounts}td>
<td>${book.detail}td>
tr>
c:forEach>
tbody>
table>
div>
div>
body>
html>
首先我们修改书籍展示的页面getAllBooks.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
书籍展示页面
<%-- 使用cdn引入 BootStrap 用于美化界面--%>
然后我们在jsp文件夹中创建一个addBook.jsp页面,用于添加书籍信息:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
添加书籍
新增书籍
然后我们继续在jsp文件夹下创建一个updateBook.jsp,用于更新书籍信息:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
添加书籍
修改书籍
然后修改BookController.java文件
package com.myLearning.controller;
import com.myLearning.pojo.Book;
import com.myLearning.service.BookService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@Controller
@RequestMapping("/book")
public class BookController {
@Autowired
@Qualifier("bookServiceImpl")
private BookService bookService;
@RequestMapping("/getAllBooks")
public String getAllBooks(Model model) {
List<Book> books = bookService.getAllBooks();
model.addAttribute("books", books);
return "getAllBooks";
}
@RequestMapping("/toAddBook")
public String toAddBook(Model model) {
return "addBook";
}
@RequestMapping("/addBook")
public String addBook(Book book, Model model) {
bookService.addBook(book);
return "redirect:/book/getAllBooks";
}
@RequestMapping("/toUpdate")
public String toUpdate(Book book, Model model) {
model.addAttribute("qBook", book);
return "updateBook";
}
@RequestMapping("/updateBook")
public String updateBook(Book book, Model model) {
bookService.updateBook(book);
return "redirect:/book/getAllBooks";
}
@RequestMapping("/deleteBook")
public String deleteBook(Book book, Model model) {
bookService.deleteBook(book);
return "redirect:/book/getAllBooks";
}
@RequestMapping("/queryBook")
public String queryBook(@RequestParam("queryName") String str, Model model) {
List<Book> books = bookService.getBookByStr(str);
if(books.isEmpty()) model.addAttribute("error", "未找到呢,亲");
model.addAttribute("books", books);
return "getAllBooks";
}
}
Ajax = Asynchronous JavaScript and XML(异步JavaScript和XML)。
Ajax是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
通过在后台与服务器进行少量数据交换,Ajax可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用Ajax)如果需要更新内容,必须重载整个网页页面。
Ajax的工作原理相当于在用户和服务器之间加了一个中间层(Ajax引擎),使用户操作与服务器响应异步化。这样把以前的一些服务器负担的工作转嫁到客户端,利于客户端闲置的处理能力来处理,减轻服务器和带宽的负担,从而达到节约ISP的空间和带宽租用成本的目的。
Ajax使用XMLHttpRequest对象和服务器通信,这种方式的通信在客户端和服务器之间建立了一条双向的通信渠道,服务器不再是被动的响应,而是主动向客户端推送信息。
jQuery为我们封装了Ajax的一些使用,让我们能够更加方便地完成ajax。
为此,我们先要导入jQuery的jar包。
我们需要访问jQuery官网,https://jquery.com/download/
然后下载Download the uncompressed development version of jQuery 3.7.1
并将下载的文件jquery-3.7.1.js 放在我们项目中,假设我们放在了/WEB-INF/statics/js目录下
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.7.1.js">script>
<script>
function uT(){
$.post({
url: "${pageContext.request.contextPath}/mySolve",
data: {"username":$("#username").val()},
success:function (res){
$("#usernamestate").text(res);
if(res==="ok"){
$("#usernamestate").css("color","green")
}
else
{
$("#usernamestate").css("color","red")
}
}
})
}
function pT(){
$.post({
url: "${pageContext.request.contextPath}/mySolve",
data: {"password":$("#password").val()},
success:function (res){
$("#passwordstate").text(res);
if(res==="ok"){
$("#passwordstate").css("color","green")
}
else
{
$("#passwordstate").css("color","red")
}
}
})
}
script>
<title>ajax异步用户登录title>
head>
<body>
<form action="" method="post">
<p>用户名:<input type="text" name="username" id="username" onblur="uT()"/> <span id="usernamestate">span>p>
<p>密码: <input type="password" name="password" id="password" onblur="pT()"/> <span id="passwordstate">span>p>
<input type="submit" />
form>
body>
html>
解析:
在这个页面中,我们让用户输入它的用户名以及密码,并且在输入框失去焦点时,调用我们在javascript中的函数uT()和pT(),这两个函数分别向服务器发送请求,获取服务器返回的数据,然后根据返回的数据来改变span标签中的内容以及颜色。
在uT()以及pt()中,我们使用jQuery的post()方法向服务器发送请求,其中,url是请求的地址,data是发送的数据,success是请求成功后执行的函数,res是服务器返回的数据。在success函数中,我们根据res的值来改变span标签中的内容以及颜色。
package com.myLearning.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class testController {
@RequestMapping("/mySolve")
public String myResolve( @RequestParam(value = "username" ,required = false) String username,
@RequestParam(value = "password" ,required = false) String password) {
if(username != null){
if(username.equals("admin")){
return "ok";
}else{
return "用户名不存在";
}
}
if(password != null){
if(password.equals("123456")){
return "ok";
}else{
return "密码不正确";
}
}
return "error";
}
}
我们此时如果直接运行我们的代码,可能会出现乱码的问题,为此我们需要在我们的sprintmvc的配置文件,假设是applicationContext.xml中添加如下配置:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="defaultCharset" value="UTF-8"/>
bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="defaultCharset" value="UTF-8"/>
bean>
list>
property>
bean>
这样就可以解决乱码的问题了
拦截器是SpringMVC中的一种机制,它可以在请求到达目标方法之前进行一些处理,也可以在目标方法执行之后进行一些处理,它的作用类似于过滤器,但是它只能拦截请求,不能拦截静态资源,它的使用步骤如下:
package com.myLearning.interceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class MyInterceptor implements HandlerInterceptor {
@Override
// 返回true表示这个拦截器放行,返回false表示拦截这个请求
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("方法执行前,拦截器进行拦截检测");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("方法执行后");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("请求完成");
}
}
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.myLearning.interceptor.MyInterceptor"/>
mvc:interceptor>
mvc:interceptors>
为了实现文件上传,首先我们需要再我们的前端表单中配置enctype的属性
这个属性的默认值为application/x-www-form-urlencoded,这种情况下会将我们的值处理为url编码,而如果我们要上传文件,那么这个属性应该设置为multipart/form-data,表示将我们的表单数据以二进制的形式进行处理
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="upload">
form>
<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"/>
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:applicationContext.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
<multipart-config>
<max-file-size>10485760max-file-size>
<max-request-size>10485760max-request-size>
<file-size-threshold>1048576file-size-threshold>
multipart-config>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
package com.myLearning.controller;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
@Controller
public class FileController {
//@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
//批量上传CommonsMultipartFile则为数组即可
@RequestMapping("/upload")
public String fileUpload(@RequestParam("file") MultipartFile file , HttpServletRequest request) throws IOException, IOException {
//获取文件名 : file.getOriginalFilename();
String uploadFileName = file.getOriginalFilename();
//如果文件名为空,直接回到首页!
if ("".equals(uploadFileName)){
return "redirect:/index.jsp";
}
System.out.println("上传文件名 : "+uploadFileName);
//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
//如果路径不存在,创建一个
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
System.out.println("上传文件保存地址:"+realPath);
InputStream is = file.getInputStream(); //文件输入流
OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流
//读取写出
int len=0;
byte[] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
return "redirect:/index.jsp";
}
}
第二种controller写法
/*
* 采用file.Transto 来保存上传的文件
*/
@RequestMapping("/upload2")
public String fileUpload2(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {
//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
//上传文件地址
System.out.println("上传文件保存地址:"+realPath);
//通过CommonsMultipartFile的方法直接写文件(注意这个时候)
file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));
return "redirect:/index.jsp";
}
@RequestMapping(value="/download")
public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
//要下载的图片地址
String path = request.getServletContext().getRealPath("/upload");
String fileName = "vertin.jpg";
//1、设置response 响应头
response.reset(); //设置页面不缓存,清空buffer
response.setCharacterEncoding("UTF-8"); //字符编码
response.setContentType("multipart/form-data"); //二进制传输数据
//设置响应头
response.setHeader("Content-Disposition",
"attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));
File file = new File(path,fileName);
//2、 读取文件--输入流
InputStream input=new FileInputStream(file);
//3、 写出文件--输出流
OutputStream out = response.getOutputStream();
byte[] buff =new byte[1024];
int index=0;
//4、执行 写出操作
while((index= input.read(buff))!= -1){
out.write(buff, 0, index);
out.flush();
}
out.close();
input.close();
return null;
}
<a href="/download">点击下载a>
https://www.bilibili.com/video/BV1aE41167Tu?vd_source=16bf0c507e4a78c3ca31a05dff1bee4e&spm_id_from=333.788.videopod.episodes