文章目录
关于SpringMVC
ssm:Spring+SpringMVC+Mybatis
- MVC三层架构:
- Model:模型(dao,service)
- View:视图(jsp)
- Controller:控制器(servlet)
- 试问:你的项目的架构,是设计好的,还是演进的?回答:ALL FROM ONE
回顾servlet
-
一个简单servlet
public class helloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1. 获取前端参数 String method = req.getParameter("method"); if (method.equals("add")){ req.getSession().setAttribute("msg","执行了add方法"); } if (method.equals("delete")){ req.getSession().setAttribute("msg","执行了delete方法"); } //2. 调用业务层 //3. 视图转发或者重定向 req.getRequestDispatcher("WEB-INF/jsp/test.jsp").forward(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
-
配置web.xml,servlet映射
<servlet> <servlet-name>hello</servlet-name> <servlet-class>com.study.servlet.helloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <!--设置超时--> <!--<session-config> <session-timeout>15</session-timeout> </session-config>--> <!--设置默认页面--> <!--<welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list>-->
-
jsp表单填写参数
<form action="/hello" method="post"> <input type="text" name="method"> <input type="submit"> </form>
-
jsp展示结果
<body> ${msg} </body>
实现SpringMVC
-
简要分析执行流程
- DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求
- 我们假设请求的url为:
http://localhost:8080/SpringMVC/hello
- 如上url拆分成三部分:
http://localhost:8080
:服务器域名SpringMVC
:部署在服务器上的web站点hello
:表示控制器- 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器
- 我们假设请求的url为:
- HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler
- HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello
- HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等
- HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler
- Handler让具体的Controller执行
- Controller将具体的执行信息返回给HandlerAdapter ,如ModelAndView
- HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet
- DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名
- 视图解析器将解析的逻辑视图名传给DispatcherServlet
- DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图
- 最终视图呈现给用户
- DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求
-
代码实现
-
配置web.xml,接管所有servlet
<!--配置DispatchServlet:这个是SpringMVC的核心; 请求分发器,前端控制器--> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--关联一个springmvc的配置文件:建议使用(spring配置文件名字)-servlet.xml--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <!--启动级别1:服务器一启动跟着启动--> <load-on-startup>1</load-on-startup> </servlet> <!-- / 匹配所有的请求(不包括.jsp)--> <!-- /* 匹配所有的请求(包括.jsp) 返回jsp视图时再次进入DispatcherServlet类, 导致找不到对应的controller报错--> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
-
springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <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"/> <!--视图解析器:DispatcherServlet给它的ModelAndView 1. 获取了ModelAndView的数据 2. 解析ModelAndView的视图名字 3. 拼接视图名字,找到对应的视图 /WEB-INF/jsp/hello.jsp 4. 将数据渲染到视图上 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <!--前缀--> <property name="prefix" value="/WEB-INF/jsp/"/> <!--后缀--> <property name="suffix" value=".jsp"/> </bean> <!--BeanNameUrlHandlerMapping:需要根据bean的id来寻找--> <!--Handler,类似于之前的servlet映射--> <bean id="/hello" class="com.study.controller.helloController"/> </beans>
-
实现Controller接口
public class helloController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { //ModelAndView 模型和视图 ModelAndView mv = new ModelAndView(); //封装对象,放在ModelAndView中.Model mv.addObject("msg","helloSpringMVC"); //封装要跳转的视图,放在ModelAndView中 mv.setViewName("hello");//拼接后:/WEB-INF/jsp/hello.jsp return mv; } }
-
jsp展示结果
<body> ${msg} </body>
-
注意:可以会出现404错误,原因是依赖没有导入项目,需要去项目结构中的Artifacts中找到Available Elements里的对应依赖放入项目
-
注解实现SpringMVC
-
使用springMVC必须配置的三大件:处理器映射器、处理器适配器、视图解析器
- 通常,我们只需要手动配置视图解析器,而处理器映射器和处理器适配器只需要开启注解驱动即可,而省去了大段的xml配置
-
代码实现
-
配置web.xml
<!--配置DispatchServlet:这个是SpringMVC的核心; 请求分发器,前端控制器--> <servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--DispatcherServlet要绑定Spring-MVC的配置文件--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springMVC-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- 在SpringMVC中, / 和 /* 的区别 /:只匹配所有的请求,不会去匹配jsp页面 /*:匹配所有的请求,包括jsp --> <servlet-mapping> <servlet-name>springMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
-
springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--自动扫描包,让指定包下的注解生效,由IOC容器统一管理--> <context:component-scan base-package="com.study.controller"/> <!--让springMVC不处理静态资源 .css .js .html .mp3 .mp4 ...--> <mvc:default-servlet-handler/> <!-- 支持mvc注解驱动: 在spring中一般采用@RequestMapping注解来完成映射关系 要想使@RequestMapping注解生效 必须向上下文中注册DefaultAnnotationHandlerMapping 和一个AnnotationMethodHandlerAdapter实例 这两个实例分别在类级别和方法级别处理 而annotation-driven配置帮助我们自动完成上述两个实例的注入 --> <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 //表示被IOC容器接管 //@RestController //不会被视图解析器处理,仅仅返回字符串(与@Controller选其一) public class helloController { @RequestMapping("/hello") //对应的url路径调用该方法,类似于之前的servlet映射 public String hello(Model model) { //封装数据 model.addAttribute("msg", "hello,SpringMVC"); return "hello"; //会被视图解析器处理,表示要跳转的视图 } }
-
RESTful风格
-
使用RESTful操作资源:可以通过不同的请求方式来实现不同的效果,如下,请求地址一样,但功能可以不同
- http://localhost:8080/item/1 查询,GET
- http://localhost:8080/item 增加,POST
- http://localhost:8080/item 更新,PUT
- http://localhost:8080/item/1 删除,DELETE
-
新建一个类,在SpringMVC中可以使用@PathVariable注解,让方法参数的值对应绑定到一个URL模板变量上
@Controller public class RestFulController { //原来的:http://localhost:8080/springMVC_4_controller_war_exploded/add?a=1&b=2 //RestFul:http://localhost:8080/springMVC_4_controller_war_exploded/add/1/2 //映射访问路径 //@RequestMapping("/add/{a}/{b}") //不同访问方式触发不同方法 GET @GetMapping("/add/{a}/{b}") public String test1(@PathVariable int a, @PathVariable int b, Model model) { int res = a + b; model.addAttribute("msg", "结果1为" + res); return "test"; } //映射访问路径,限定必须是GET请求 //@RequestMapping(value = "/add", method = {RequestMethod.GET}) //不同访问方式触发不同方法 POST @PostMapping("/add/{a}/{b}") public String test2(@PathVariable int a, @PathVariable int b, Model model) { int res = a + b; model.addAttribute("msg", "结果2为" + res); return "test"; } }
-
使用路径变量的好处:
- 使路径变得更加简洁
- 获得参数更加方便,框架会自动进行类型转换
- 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法,如这里访问是的路径是/add/1/a,则路径与方法不匹配,而不会是参数转换失败
-
小结:
- SpringMVC的@RequestMapping注解能够处理HTTP请求的方法,比如GET,PUT,POST,DELETE以及PATCH
- 所有的地址栏请求默认都会是HTTP GET类型
- 方法级别的注解变体有如下几个:(组合注解)
- @GetMapping(= @RequestMapping(method = RequestMethod.GET)的一个快捷方式)
- @PostMapping
- @DeleteMapping
- @PatchMapping
重定向和转发
-
重定向
@Controller public class controllerTest2 { @RequestMapping("/t2") public String test(Model model){ //重定向,默认是转发,加了redirect:/变为重定向 model.addAttribute("msg","controllerTest2"); return "redirect:/index.jsp"; } }
-
重定向不会走视图解析器的,转发才会。并且重定向不能访问WEB-INF目录下的内容。想要通过重定向访问WEB-INF目录下的内容,可以通过另外一个方法转发跳转到jsp
接受请求参数及数据回显
-
提交的域名称和处理方法的参数名一致
@Controller @RequestMapping("/user") public class UserController { //localhost:8080/user/t1?name=xxx @GetMapping("/t1") public String test1(String name, Model model) { //1. 接收前端参数 System.out.println("接收到前端的参数为:" + name); //2. 将返回的结果传递给前端 model.addAttribute("msg", name); //3. 视图跳转 return "test"; } //前端接收的是一个对象:id, name, age /* * 1. 接收前端用户传递的参数,判断参数的名字,假设名字直接在方法上,可以直接使用 * 2. 假设传递的是一个对象User,匹配User对象中的字段名:如果名字一致则OK,否则匹配不到 * */ @GetMapping("/t2") public String test2(User user) { System.out.println(user); return "test"; } }
-
提交的域名称和处理方法的参数名不一致
@Controller @RequestMapping("/user") public class UserController { //localhost:8080/user/t1?name=xxx @GetMapping("/t1") public String test1(@RequestParam("username") String name, Model model) { //1. 接收前端参数 System.out.println("接收到前端的参数为:" + name); //2. 将返回的结果传递给前端 model.addAttribute("msg", name); //3. 视图跳转 return "test"; } }
乱码问题解决
-
加过滤器(自己写)
-
编写过滤器类
public class EncodingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletRequest.setCharacterEncoding("utf-8"); servletResponse.setCharacterEncoding("utf-8"); filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } }
-
web.xml里加入过滤器配置
<filter> <filter-name>encoding</filter-name> <filter-class>com.study.filter.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>encoding</filter-name> <!--拦截所有文件--> <url-pattern>/*</url-pattern> </filter-mapping>
-
-
SpringMVC提供的过滤器
-
web.xml里加入配置
<filter> <filter-name>encoding</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> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
-
Controller返回JSON数据
什么是JSON
-
JSON(JavaScript Object Notation),JS对象标记,是一种轻量级的数据交换格式,目前使用特别广泛
-
采用完全独立于编程语言的文本格式来存储和表示数据
-
简洁和清晰的层次结构使得JSON成为理想的数据交换语言
-
易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率
-
JSON键值对是用来保存JavaScript对象的一种方式,和JavaScript对象的写法也大同小异,键/值对组合中的键名写在前面并用双引号包裹,使用冒号分隔,然后写值:
{"name" : "cbc"} {"age" : "3"} {"sex" : "男"}
-
json和js对象互转
<script type="text/javascript"> //编写一个JavaScript对象 let user = { name: "cbc", age: 3, sex: "男" }; //将js对象转换为json对象 let json = JSON.stringify(user); console.log(json); //将json对象转换为js对象 let obj = JSON.parse(json); console.log(obj); //console.log(user); </script>
Jackson使用
-
Jackson应该是目前比较好的json解析工具了
-
当然工具不止这一个,比如还有阿里巴巴的fastjson等等
-
我们这里使用Jackson,使用它需要导入它的jar包
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.12.1</version> </dependency>
-
发现乱码,需要设置一下编码格式utf-8,以及它的返回值类型
-
通过@RequestMapping的produces属性来实现(原生解决方法)
//produces:指定响应体返回类型和编码 @RequestMapping(value = "/j1", produces = "application/json;charset=utf-8")
-
我们可以在SpringMVC的配置文件上添加一段消息StringHttpMessageConverter转换配置
<!--JSON乱码问题配置--> <mvc:annotation-driven> <mvc:message-converters> <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>
-
-
传对象和对象集合(类上事先加好@RestController,或者在方法上加@ResponseBody)
@RequestMapping("/j1") public String json1() throws JsonProcessingException { //用jackson的ObjectMapper类处理对象 ObjectMapper mapper = new ObjectMapper(); //创建一个对象 User user = new User("cbc",3,"男"); //把对象参数和属性转换成字符串 String string = mapper.writeValueAsString(user); return string; }
@RequestMapping("/j2") public String json2() throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); List<User> users = new ArrayList<>(); User user0 = new User("cbc0",3,"男"); User user1 = new User("cbc1",3,"男"); User user2 = new User("cbc2",3,"男"); User user3 = new User("cbc3",3,"男"); User user4 = new User("cbc4",3,"男"); User user5 = new User("cbc5",3,"男"); users.add(user0); users.add(user1); users.add(user2); users.add(user3); users.add(user4); users.add(user5); String string = mapper.writeValueAsString(users); return string; }
-
传时间
@RequestMapping("/j3") public String json3() throws JsonProcessingException { //ObjectMapper,时间解析后的默认格式为:Timestamp,时间戳 ObjectMapper mapper = new ObjectMapper(); Date date = new Date(); //自定义日期格式 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //方法2:使用ObjectMapper来格式化输出,关闭时间戳,设置日期格式 /*mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); mapper.setDateFormat(simpleDateFormat); return mapper.writeValueAsString(date);*/ //方法1:直接定义日期格式处理date return mapper.writeValueAsString(simpleDateFormat.format(date)); }
封装思想:写json工具类
-
工具类
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) { //由于重载方法偷了点懒,所以此处只能用方法2处理日期格式,用方法1会报错 ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false); SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat); mapper.setDateFormat(simpleDateFormat); try { return mapper.writeValueAsString(object); } catch (JsonProcessingException e) { e.printStackTrace(); } return null; } }
-
使用工具类
@RequestMapping("/j4") public String json4(){ Date date = new Date(); return JsonUtils.getJson(date,"yyyy-mm-dd hh:mm:ss"); } @RequestMapping("/j5") public String json5() throws JsonProcessingException { List<User> users = new ArrayList<>(); User user0 = new User("cbc0",3,"男"); User user1 = new User("cbc1",3,"男"); User user2 = new User("cbc2",3,"男"); User user3 = new User("cbc3",3,"男"); User user4 = new User("cbc4",3,"男"); User user5 = new User("cbc5",3,"男"); users.add(user0); users.add(user1); users.add(user2); users.add(user3); users.add(user4); users.add(user5); return JsonUtils.getJson(users); }
FastJson使用
-
fastjson.jar是阿里开发的一款专门用于Java开发的包,可以方便的实现json对象与JavaBean对象的转换,实现JavaBean对象与json字符串的转换,实现json对象与json字符串的转换。实现json的转换方法很多,最后的实现结果都是—样的
-
fastjson的pom依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency>
-
fastjson三个主要类:
- JSONObject:代表json对象
- JSONObject实现了Map接口,猜想JSONObject底层操作是由Map实现的
- JSONObject对应json对象,通过各种形式的get()方法可以获取json对象中的数据,也可利用诸如size(),isEmpty()等方法获取"键/值"对的个数和判断是否为空。其本质是通过实现Map接口并调用接口中的方法完成的
- JSONArray:代表json对象数组
- 内部是有List接口中的方法来完成操作的
- JSON:代表JSONObject和JSONArray的转化
- JSON类源码分析与使用
- 仔细观察这些方法,主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化
- JSONObject:代表json对象
-
fastjson使用
@RequestMapping("/j6") @ResponseBody public String json6() throws JsonProcessingException { List<User> users = new ArrayList<>(); User user0 = new User("cbc0",3,"男"); User user1 = new User("cbc1",3,"男"); User user2 = new User("cbc2",3,"男"); User user3 = new User("cbc3",3,"男"); User user4 = new User("cbc4",3,"男"); User user5 = new User("cbc5",3,"男"); users.add(user0); users.add(user1); users.add(user2); users.add(user3); users.add(user4); users.add(user5); String string = JSON.toJSONString(users); return string; }
-
fastjson常用方法
- 解析为java对象(支持深度解析)
T t = JSON.parseObject(jsonstr, T.class); //解析{...}为对象
List<t> list = JSON.parseArray(jsonstr, T.class); //解析[{},{}...]为集合
- JSON字符串解析为JSON对象
- 如果不知道json字符串具体是JSONObject还是JSONArray可以使用
Object obj = JSON.parse(jsonstr); // obj可能为String、JSONArray、JSONObject
- 如果确定字符串为JSONObject类型
JSONObject parseObject = JSON.parseObject(jsonstr);
- 如果确定字符串为JSONArray类型
JSONArray jsonarray = JSON.parseArray(jsonstr);
- 如果不知道json字符串具体是JSONObject还是JSONArray可以使用
- java对象解析为JSON对象
JSONObject json = (JSONObject) JSON.toJSON(bean);
- JSON对象解析为java对象
Bean bean = JSON.toJavaObject(jsonobject, Bean.class);
- 解析为java对象(支持深度解析)
SSM整合
-
导入依赖
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency> <!--数据库连接池:c3p0--> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency> <!--Servlet JSP--> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!--Mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.3</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.5</version> </dependency> <!--Spring--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.4</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.4</version> </dependency> </dependencies> <!--静态资源导出问题--> <!--<build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>-->
-
编写database.properties用于关联数据库
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC jdbc.username=root jdbc.password=123456
-
创建spring配置文件applicationContext.xml,编写mybatis-config.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!--配置数据源,现在交给spring去做--> <!--开启mybatis自带日志--> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <!--别名--> <typeAliases> <package name="com.pp.pojo"/> </typeAliases> <!--映射mapper.xml--> <mappers> <mapper resource="dao/BookMapper.xml"/> </mappers> </configuration>
-
建好必要的包,编写实体类
public class Books { private int bookID; private String bookName; private int bookCounts; private String detail;
-
编写dao层接口
public interface BookMapper { //增加一本书 int addBook(Books books); //删除一本书 int deleteBookById(@Param("bookId") int id); //更新一本书 int updateBook(@Param("books") Books books, @Param("bookId") int id); //查询一本书 Books queryBookById(@Param("bookId") int id); //查询全部书 List<Books> queryAllBook(); }
-
编写mapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.pp.dao.BookMapper"> <insert id="addBook" parameterType="Books"> insert into books (bookName, bookCounts, detail) values (#{bookName}, #{bookCounts}, #{detail}); </insert> <delete id="deleteBookById" parameterType="int"> delete from books where bookID = #{bookId} </delete> <update id="updateBook"> update books set bookName=#{books.bookName}, bookCounts=#{books.bookCounts}, detail=#{books.detail} where bookID = #{bookId}; </update> <select id="queryBookById" parameterType="int" resultType="Books"> select * from books where bookID = #{bookId}; </select> <select id="queryAllBook" resultType="Books"> select * from books; </select> </mapper>
-
编写service层接口
public interface BookService { //增加一本书 int addBook(Books books); //删除一本书 int deleteBookById(@Param("bookId") int id); //更新一本书 int updateBook(@Param("books") Books books, @Param("bookId") int id); //查询一本书 Books queryBookById(@Param("bookId") int id); //查询全部书 List<Books> queryAllBook(); }
-
编写service接口实现类
public class BookServiceImpl implements BookService { //service调dao层:组合DAO private BookMapper bookMapper; public void setBookMapper(BookMapper bookMapper) { this.bookMapper = bookMapper; } @Override public int addBook(Books books) { return bookMapper.addBook(books); } @Override public int deleteBookById(int id) { return bookMapper.deleteBookById(id); } @Override public int updateBook(Books books, int id) { return bookMapper.updateBook(books, id); } @Override public Books queryBookById(int id) { return bookMapper.queryBookById(id); } @Override public List<Books> queryAllBook() { return bookMapper.queryAllBook(); } }
-
编写spring-dao.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <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" 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"> <!--1. 关联数据库配置文件--> <context:property-placeholder location="classpath:database.properties"/> <!--2. 连接池 dbcp:半自动化操作,不能自动连接 c3p0:自动化操作(自动化的加载配置文件,并且可以自动设置到对象中) druid hikari --> <bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <!--c3p0连接池私有属性--> <!--<property name="maxPoolSize" value="30"/> <property name="minPoolSize" value="10"/> <!–关闭连接后不自动commit–> <property name="autoCommitOnClose" value="false"/> <!–获取连接超时时间–> <property name="checkoutTimeout" value="10000"/> <!–当获取连接失败重试次数–> <property name="acquireRetryAttempts" value="2"/>--> </bean> <!--3. sqlSessionFactory 这里的id必须跟下面sqlSessionFactoryBeanName的值相同--> <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory"> <property name="dataSource" ref="dataSource"/> <!--绑定mybatis的配置文件--> <property name="configLocation" value="classpath:mybatis-config.xml"/> </bean> <!--4. 配置dao接口扫描包,动态的实现了dao接口注入到spring容器中--> <!--MapperScannerConfigurer会扫描包中的所有接口,把每个接口都执行一次getMapper()方法, 得到每个接口的对象--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!--注入sqlSessionFactory 属性的值必须与上面SqlSessionFactoryBean的id相同--> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> <!--要扫描的dao包--> <property name="basePackage" value="com.pp.dao"/> </bean> </beans>
-
编写spring-service.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <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" 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"> <!--1. 扫描service下的包--> <context:component-scan base-package="com.pp.service"/> <!--2. 将所有业务类注入到spring,可以通过配置或注解--> <bean class="com.pp.service.BookServiceImpl" id="bookServiceImpl"> <property name="bookMapper" ref="bookMapper"/> </bean> <!--3. 声明式事务配置--> <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"> <!--注入数据源--> <property name="dataSource" ref="dataSource"/> </bean> <!--4. aop横切事务支持--> </beans>
-
把有关spring的所有配置文件整合到applicationContext.xml中
<?xml version="1.0" encoding="UTF-8"?> <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"> <import resource="classpath:spring-dao.xml"/> <import resource="classpath:spring-service.xml"/> <!--spring-mvc.xml在后续编写--> <import resource="classpath:spring-mvc.xml"/> </beans>
-
添加web框架支持,配置web.xml
<!--配置DispatchServlet--> <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:applicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!--乱码过滤--> <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> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--Session--> <session-config> <session-timeout>15</session-timeout> </session-config>
-
编写spring-mvc.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!--1. 注解驱动--> <mvc:annotation-driven/> <!--2. 静态资源过滤--> <mvc:default-servlet-handler/> <!--3. 扫描包:controller--> <context:component-scan base-package="com.pp.controller"/> <!--4. 视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> </beans>
Ajax技术
- 简介:
- AJAX = Asynchronous JavaScript and XML(异步的JavaScript和XML)
- Ajax是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术
- Ajax不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术
- 在2005年,Google通过其Google Suggest使AJAX变得流行起来。Google Suggest能够自动帮你完成搜索单词
- Google Suggest使用AJAX创造出动态性极强的web界面:当您在谷歌的搜索框输入关键字时,JavaScript 会把这些字符发送到服务器,然后服务器会返回一个搜索建议的列表
jQuery.ajax
-
纯JS原生实现Ajax我们不去讲解这里,直接使用jquery提供的,方便学习和使用,避免重复造轮子,有兴趣可以去了解下JS原生XMLHttpRequest
-
Ajax的核心是XMLHttpRequest对象(XHR)。XHR为向服务器发送请求和解析服务器响应提供了接口。能够以异步方式从服务器获取新数据
-
jQuery提供多个与AJAX有关的方法
-
通过jQuery AJAX方法,您能够使用HTTP Get和 HTTP Post从远程服务器上请求文本、HTML、XML或JSON同时您能够把这些外部数据直接载入网页的被选元素中
-
jQuery不是生产者,而是大自然搬运工,它是一个库,含有大量js函数(方法)
-
jQuery Ajax本质就是XMLHttpRequest,对他进行了封装,方便调用
-
实现ajax
-
导入jQuery.js,spring配置文件中一定要加上静态资源过滤配置
-
编写controller
@RequestMapping("/test") @ResponseBody public String t1(Model model){ List<User> users = new ArrayList<>(); User user0 = new User("cbc0", 3, "男"); User user1 = new User("cbc1", 3, "男"); User user2 = new User("cbc2", 3, "男"); User user3 = new User("cbc3", 3, "男"); User user4 = new User("cbc4", 3, "男"); User user5 = new User("cbc5", 3, "男"); users.add(user0); users.add(user1); users.add(user2); users.add(user3); users.add(user4); users.add(user5); model.addAttribute("msg",users); return "test2"; }
-
编写test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.js"> </script> <script> //加这个$(function){}是为了让dom结构加载完后再执行代码 $(function () { $("#btn").click(function () { /* * $.post(url, param可省略, success) * */ $.post("${pageContext.request.contextPath}/a2", function (data) { let html; for (let i = 0; i < data.length; i++) { html += "<tr>" + "<td>" + data[i].name + "</td>" + "<td>" + data[i].age + "</td>" + "<td>" + data[i].sex + "</td>" + "</tr>" } $("#content").html(html); }) }) }); /*function x() { $.post("${pageContext.request.contextPath}/a2", function (data) { let html; for (let i = 0; i < data.length; i++) { html += "<tr>" + "<td>" + data[i].name + "</td>" + "<td>" + data[i].age + "</td>" + "<td>" + data[i].sex + "</td>" + "</tr>" } $("#content").html(html); }) }*/ </script> </head> <body> <div> <input type="button" value="加载数据" id="btn" <%--οnclick="x()"--%>> <table> <tr>姓名</tr> <tr>年龄</tr> <tr>性别</tr> <tbody id="content"> </tbody> </table> </div> </body> </html>
-
拦截器
-
SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能
-
过滤器与拦截器的区别:拦截器是AOP思想的具体应用
-
过滤器
- servlet规范中的一部分,任何java web工程都可以使用
- 在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截
-
拦截器
- 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
- 拦截器只会拦截访问的控制器(controller)方法,如果访问的是jsp/html/css/image/js是不会进行拦截的
-
自定义拦截器
-
想要自定义拦截器,必须实现HandlerInterceptor接口
-
编写拦截器
public class MyInterceptor implements HandlerInterceptor { //return true; 执行下一个拦截器,放行 //return false; 不执行下一个拦截器,拦截 @Override 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.study.config.MyInterceptor"/> </mvc:interceptor> </mvc:interceptors>
-
登录判断验证
-
编写拦截器
public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(); //放行:判断什么情况下登录 if (session.getAttribute("userLoginInfo") != null) { return true; } //登录提交放行 if (request.getRequestURI().contains("login")) { return true; } //跳转登录页面放行 if (request.getRequestURI().contains("goLogin")) { return true; } //这个地方不能用重定向,重定向是客户端级别的,不能走WEB-INF里的页面 request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response); return false; } }
-
编写拦截器配置
<!--拦截器配置--> <mvc:interceptors> <mvc:interceptor> <!-- /** 包括这个请求下面的所有请求--> <mvc:mapping path="/User/**"/> <!--执行下面这个拦截器--> <bean class="com.study.config.LoginInterceptor"/> </mvc:interceptor> </mvc:interceptors>
-
编写Controller
@Controller @RequestMapping("/User") public class LoginController { @RequestMapping("/login") public String login(HttpSession session, String username, String password, Model model) { //把用户的信息存在session中 session.setAttribute("userLoginInfo", username); model.addAttribute("username", username); return "main"; } @RequestMapping("/main") public String main(){ return "main"; } @RequestMapping("/goLogin") public String goLogin(){ return "login"; } @RequestMapping("goOut") public String goOut(HttpSession session){ session.removeAttribute("userLoginInfo"); return "redirect:/index.jsp"; } }
-
编写默认页面、登录页面、主页
<body> <a href="${pageContext.request.contextPath}/User/goLogin">登录页面</a> <a href="${pageContext.request.contextPath}/User/main">主页</a> </body>
<body> <%--在WEB-INF下的所有页面或者资源,只能通过controller,或者servlet进行访问--%> <h1>登录页面</h1> <form action="${pageContext.request.contextPath}/User/login" method="post"> 用户名:<input type="text" name="username"> 密码:<input type="text" name="password"> <input type="submit" value="提交"> </form> </body>
<body> <h1>主页</h1> <span>${username}</span> <p> <a href="${pageContext.request.contextPath}/User/goOut">注销</a> </p> </body>
文件上传和下载
-
导入依赖
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency>
-
文件上传
-
编写xml配置
<!--文件上传配置 id只能用multipartResolver--> <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver"> <!--请求的编码格式,必须和jsp的pageEncoding属性一致,以便正确读取表单的内容, 默认为ISO-8859-1--> <property name="defaultEncoding" value="utf-8"/> <!--上传文件大小上限,单位为字节 10485760=10M--> <property name="maxUploadSize" value="10485760"/> <property name="maxInMemorySize" value="40960"/> </bean>
-
编写Controller
@RestController public class FileController { @RequestMapping("/upload") public void fileUpload(@RequestParam("file") CommonsMultipartFile 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())); } }
-
-
文件下载
-
正常情况用a标签也能实现
-
使用io流方法:
-
编写Controller
@RequestMapping("/download") public void fileDownload(HttpServletResponse response, HttpServletRequest request) throws Exception { //要下载的图片地址 String path = request.getServletContext().getRealPath("/upload"); String fileName = "1.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. 读取文件--输入流 FileInputStream input = new FileInputStream(file); //3. 写出文件--输出流 ServletOutputStream 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(); }
-
-