ssm框架学习笔记_recordservice-程序员宅基地

技术标签: Spring&微服务  


title: ssm框架学习笔记
date: 2018-03-21 16:49:52
updated: 2020-03-12 14:34:23
categories: spring
tags:
- spring


此文档记录研二学习ssm框架的知识点笔记

SSM简介

最初:jsp + servlet + jdbc

现在:springmvc + spring + mybatis

官网地址:

logback配置:https://logback.qos.ch/manual/configuration.html

spring-api-doc:https://docs.spring.io/spring/docs/

mybatis中文官网:http://www.mybatis.org/mybatis-3/zh/index.html

Bean容器初始化

1583753997

一、Spring常用的三种注入方式

Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式主要有三种:setter设值注入,构造注入,基于注解的注入。
1583754027
1583754035

基于注解的注入

基于注解的注入:注解方式注册bean,注入依赖

  • 主要有四种注解可以注册bean,每种注解可以任意使用,只是语义上有所差异:
@Component:可以用于注册所有bean
​@Repository:主要用于注册dao层的bean
​@Controller:主要用于注册控制层的bean
​@Service:主要用于注册服务层的bean

  • 描述依赖关系主要有两种

@Resource:java的注解,默认以byName的方式去匹配与属性名相同的bean的id,如果没有找到就会以byType的方式查找,如果byType查找到多个的话,使用@Qualifier注解(spring注解)指定某个具体名称的bean。

​```
@Resource
@Qualifier(“userDaoMyBatis”)
private IUserDao userDao;

public UserService(){

}


@Autowired:spring注解,默认也是以byName的方式去匹配与属性名相同的bean的id,如果没有找到,就通过byType的方式去查找,如果查找到多个,用@Qualifier注解限定具体使用哪个。

@Autowired @Qualifier(“userDaoJdbc”)
​ private IUserDao userDao;

​```

二、spring学习之AOP

入门请参考:Spring AOP入门Demo
Java Spring AOP用法

AOP实现方式

1.预编译

  • AspectJ

2.运行期动态代理(JDK动态代理、CGLib动态代理)

  • SpringAOP、JbossAOP

Schema-based AOP(基于XML配置实现的SpringAOP)

Spring 所有的切面和通知器都必须放在一个<aop:config>内(可以包含多个<aop:config>元素),每一个<aop:config>可以包含pointcut, advisor和aspect元素(它们必须按照这个顺序声明)

<bean id="car" class="com.braincao.aop.car.Car"></bean>
<bean id="carLogger" class="com.braincao.aop.car.CarLogger"></bean>
	
  <aop:config>
        <!--指定切面-->
        <aop:aspect id="carLoggerAOP" ref="carLogger">
            <!--定义切点-->
            <aop:pointcut id="go" expression="execution(* com.braincao.aop.car.Car.go(..))"></aop:pointcut>
            <!--定义连接点-->
            <aop:after-returning method="beforeRun" pointcut-ref="go"></aop:after-returning>
            <aop:after method="afterRun" pointcut-ref="go"></aop:after>
        </aop:aspect>
  </aop:config>
 

特点

由Spring创建了一个car对象。Spring在创建该对象时,发现它的一个方法被配置成了切点(pointcut),所以,在实例化该对象时,会创建一个代理对象当切点方法go()执行时,会被Spring创建的代理对象所拦截,运行go方法之前,会调用所对应的切面类CarLogger的前置方法beforeRun(),然后调用Car.go()方法,再然后就调用切面类CarLogger的后置方法afterRun()。

基于注解实现的SpringAOP

看完关于ioc,bean装载和aop之后的思考

IOC即DI,不必调用者自己去new被调用对象,而是通过spring IOC容器把配置好的bean对象注入,可以通过设置注入即setter方法和构造器注入。bean装载可以通过xml配置设定,也可以同过设定扫描路径,然后通过注解来让容器识别到要装载的bean。aop面向切面编程,切面与业务是垂直的,不同业务往往都要做一些公共的类似的额外操作,在业务之前做,或在业务之后做,或在业务出了异常时做,或者在业务前后都要做,甚至这些要做的额外操作要用到业务本身的输入参数和业务完成的输出结果。比如业务一般都得记录日志,比如涉及数据更新的业务完成后都得伴随数据库操作,账户各种操作前都要验证用户权限,这些业务伴随的操作往往大致相似,如果每个业务都要写这些操作,特别繁琐,把这些操作提出来就成了切面,与业务分离。xml 和API方式都可以实现aop配置,pointcut是业务,aspect是切面,它俩怎么交互执行,怎么传参和调用结果,都可以通过xml和API方式实现。另外还有配置代理这一块比较蒙逼。最牛逼的是,之前看得傻了眼那么繁琐和复杂的xml,api方式用简单直观的aspectj方式竟然能等效实现,用的纯Java标签,在xml 里设一下自动代理。不过仅仅@Aspect容器不识别,要加上@Component 才识别。我觉得标签简直就是福音,差点我就被吓的放弃了。我以为一辈子就只能写xml了。orz。。。

1、若代理类有接口,使用JDK代理。也可以通过设置proxyTargetClass为true,强制使用CGLIB代理

1、若代理类无接口,使用CGLIB代理

3、如果proxyInterfaces属性被设置为一个或者多个全限定接口名,则使用JDK代理;如果该属性没有被设置,但是目标类实现了接口,也使用JDK代理。

三、Spring事务管理

事务:指的是逻辑上的一组操作,这组操作要么全部成功,要么全部失败

Spring事务管理主要包含3个接口

  • PlatformTransactionManager–事务管理器

  • TransactionDefinition–事务定义信息(隔离、传播、超时、只读)

  • TransactionStatus–事务具体运行状态

以上三个接口详细看Spring api即可,下面简要介绍几个重点知识。

PlatformTransactionManager–事务管理器

1583754072

TransactionDefinition–事务定义信息(隔离、传播、超时、只读)

事务的传播行为:web层->业务层(Service)->持久层(DAO)

1583754081

TransactionStatus–事务具体运行状态

Spring事务管理

spring支持两种方式事务管理:

  • 编程式事务管理

    在实际应用中很少使用,通过TransactionTemplate手动管理事务

  • 使用XML配置声明式事务

    开发中推荐使用(代码侵入性最小),spring的声明式事务是通过AOP实现的

spring事务实践–转账案例

具体可看 转账案例

声明式事务管理的三种方式

详情参考声明式事务管理的三种方式

声明式事务管理的三种方式:基于TransactionProxyFactoryBean的方式(很少使用),基于AspectJ的配置方式(经常),以及基于注解的方式(经常)。

基于TransactionProxyFactoryBean的方式

1583754099

基于TransactionProxyFactoryBean的方式不常用,因为要对需要事务的每个类都设置一个代理类,繁琐

基于AspectJ的配置方式

	<!--配置事务管理器-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	    <!--配置连接池-->
	    <property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!--配置事务的通知(事务增强)(基于aspectj声明式事务管理)-->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
	    <tx:attributes>
	        <!--
	            propagation      :传播事务行为
	            isolation        :事务隔离级别
	            read             :只读
	            rollback-for     :发生哪些异常回滚
	            no-rollback-for  :发生哪些异常不回滚
	        -->
	        <tx:method name="transfer" propagation="REQUIRED"/>
	    </tx:attributes>
	</tx:advice>
	
	<!--配置aop-->
	<aop:config>
	    <!--配置切入点 AccountService+表示所有其子类-->
	    <aop:pointcut id="pointcut" expression="execution(* transactiondemo02.service.AccountService+.*(..))"></aop:pointcut>
	    <!--配置切面:表示在pointcut切入点上应用txAdvice增强-->
	    <!--advisor表示有一个切入点的,aspect表示有多个切入点的-->
	    <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"></aop:advisor>
	</aop:config>
	

基于注解的事务管理配置方式

很明显这个更简单啊!

xml:

	<!--配置事务管理器-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	    <!--配置连接池-->
	    <property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!--开启注解事务-->
	<tx:annotation-driven transaction-manager="transactionManager"/>
	

ServiceImpl:

	//注解式的事务管理
	@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT))
	public class AccountServiceImpl implements AccountService {

@Transactional的属性:

​```
propagation :传播事务行为
isolation :事务隔离级别
readOnly :只读
rollbackFor :发生哪些异常回滚
noRollbackFor :发生哪些异常不回滚


## 四、Spring MVC

mvc: Model-Viewer-Controller

mvc的核心思想是业务数据**抽取**同业务数据**呈现**相**分离**。

前端控制器Front Controller(MVC)

![1583754122](https://img.braincao.cn/blogimg/1583754122.jpg)

Spring MVC为我们提供了一个基于组件和松耦合的MVC实现框架。在使用Java中其它MVC框架多年之后,面对Spring MVC有一种相见恨晚的感觉。Spring MVC是如此的优雅,轻盈与简洁, 让人从其它框架的桎梏解脱出来。

SpringMVC是一个基于DispatcherServlet的MVC框架,每一个请求最先访问的都是DispatcherServlet,DispatcherServlet负责转发每一个Request请求给相应的Handler,Handler处理以后再返回相应的视图(View)和模型(Model),返回的视图和模型都可以不指定,即可以只返回Model或只返回View或都不返回。SpringMVC是基于DispatcherServlet的,DispatcherServlet是继承自HttpServlet的,HttpServlet是在web.xml文件中声明的。(相关配置请左转至: maven_pom等相关配置)

![1583754147](https://img.braincao.cn/blogimg/1583754147.png)

如图,其中我们最主要写的就是Controller,其他的基本都是框架的东西。

### Spring MVC具体的项目实践

详情参考下面,重点学习了四大块:

- 基本的controller编写
- 数据绑定
- 文件上传
- json协同

视频:[Spring MVC实操](https://www.imooc.com/video/7681)

视频太慢并且已经看完,复习直接看这个人的同步笔记即可[Spring MVC起步](https://www.cnblogs.com/zjfjava/p/6746704.html)

这个视频我自己学习实践的同步工程也已上传到github了,直接看自己的项目工程即可**[springmvc_demoproject](https://github.com/braincao/springmvc_demoproject)**

注意:项目工程的WEB-INF下所有文件是私有的,必须经过后端调用才能访问到的,如果要公共访问的东西需要放在webapps目录下

### controller三种方式

controller的多种操作:基本的controller编写、数据绑定、文件上传、json协同

```java
package com.braincao.controller;
import com.braincao.model.Course;
import com.braincao.service.CourseService;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
	
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.Map;
	
@Controller
@RequestMapping("/courses")
public class CourseController {
    private CourseService courseService;
	
    @Autowired
    public void setCourseService(CourseService courseService) {
        this.courseService = courseService;
    }
	
    //法一:本方法将处理http://localhost:8080/courses/view?courseId=123
    //此方法url中必须指定?courseId=xxx的参数名courseId,参数名不可自适应改变,不好
    // @RequestParam 和@PathVariable绑定了请求中的参数。@RequestParam("courseId")显式指明参数
    @RequestMapping(value = "/view", method = RequestMethod.GET)
    public String viewCourse(@RequestParam("courseId") Integer courseId, Model model){//Model就是spring mvc的部分
        Course course = courseService.getCoursebyId(courseId);
        model.addAttribute(course);//将查询到的course放到model中
        return "course_overview";//返回jsps目录下的course_overview.jsp
    }
	
    //法二:这个方法就不用指定参数名courseId了,自动识别/view2/后面的东西并放到mvc中
    @RequestMapping(value = "/view2/{courseId}", method = RequestMethod.GET)
    public String viewCourse2(@PathVariable("courseId") Integer courseId, Map<String, Object> model){//Model就是spring mvc的部分
        Course course = courseService.getCoursebyId(courseId);
        model.put("course", course);//将查询到的course放到model中
        return "course_overview";//返回jsps目录下的course_overview.jsp
    }
	
    //法三:上面两种方法都是spring mvc方法,下面这个是传统的HttpServletRequest方法
    //处理/courses/view3?courseId=123形式的url
    @RequestMapping(value = "/view3", method = RequestMethod.GET)
    public String viewCourse3(HttpServletRequest request){
        Integer courseId = Integer.valueOf(request.getParameter("courseId"));
        Course course = courseService.getCoursebyId(courseId);
        request.setAttribute("course", course);//将查询到的course放到model中
        return "course_overview";//返回jsps目录下的course_overview.jsp
    }
	
    //绑定binding:将请求中的字段(前端)按照名字匹配原则填入模型对象(后端)
    //处理/courses/create?add形式的url来创建表单,表示一个参数params = "add"
    @RequestMapping(value = "/create", method=RequestMethod.GET, params = "add")
    public String createCourse(){
        return "admin_create/edit";//二级目录也能行哦
    }
	
    //绑定binding法一:不用@ModelAttribute
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    public String doSave(Course course){
        //这里进行业务操作,比如数据库持久化
        course.setCourseId(456);
        return "redirect:view2/" + course.getCourseId();//请求重定向:因为这里提交表单后courseId更新了,需要请求重定向,这样就完成更新
    }
	
    //绑定binding法二:用@ModelAttribute也可以
    @RequestMapping(value = "/save2", method = RequestMethod.POST)
    public String doSave2(@ModelAttribute Course course){
        //这里进行业务操作,比如数据库持久化
        course.setCourseId(456);
        return "redirect:view2/" + course.getCourseId();//请求重定向:因为这里提交表单后courseId更新了,需要请求重定向,这样就完成更新
    }
	
    //文件上传的controller
    @RequestMapping(value = "/upload", method = RequestMethod.GET)
    public String showUploadPage(){
        return "admin_upload/edit";
    }
	
    @RequestMapping(value = "/doUpload", method = RequestMethod.POST)
    public String showUploadPage(@RequestParam("file") MultipartFile file) throws IOException {//file从页面上来
        if(!file.isEmpty()){//无损的(InputStream)将上传的文件保存到指定目录下,并返回success界面
            FileUtils.copyInputStreamToFile(file.getInputStream(), new File("/Users/braincao", System.currentTimeMillis()+file.getOriginalFilename()));
        }
        return "admin_upload/success";
    }
	
    //JSON格式的前后端交互之一:给定courseId,返回对应课程的json数据,给前端展示
    @RequestMapping(value="/{courseId}", method = RequestMethod.GET)
    public @ResponseBody Course getCourseInJson(@PathVariable Integer courseId){
        return courseService.getCoursebyId(courseId);
    }
	
    //上面方法的第二种实现(泛型实现)。这两种都可以
    @RequestMapping(value="/jsontype/{courseId}", method = RequestMethod.GET)
    public ResponseEntity<Course> getCourseInJson2(@PathVariable Integer courseId){
        Course course = courseService.getCoursebyId(courseId);
        return new ResponseEntity<Course>(course, HttpStatus.OK);
    }
	
    //JSON格式的前后端交互之二:异步方式获取数据,前端通过js代码(ajax)来整合页面,
    // 即前端写个框架本来没数据,运行时异步加载获取数据填充到界面中,
    // 且注意前端的这个加载页面一定要放在webapps下,WEB-INF是私有的不能访问
    // 现在用上面两个已实现的json交互方法进行:前端异步加载后端json数据的demo。给定json数据,返回对应课程的信息,前端展示信息界面
    //启动tomcat后直接浏览器访问http://localhost:8080/courses_json.jsp?courseId=123即可
}

Ajax异步获取服务端json数据并动态加载前端页面

启动tomcat后直接浏览器访问http://localhost:8080/courses_json.jsp?courseId=123即可

webapps目录下的courses_json.jsp:

	<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
	<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><!--将jstl标签库引入此.jsp文件,简化jsp开发-->
	<!DOCTYPE html PUBLIC "-//W3C//DTD//XHTML 1.0 Transitional//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
	<html>
	<head>
	    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
	    <title>前端异步加载后端json数据的demo</title>
	    <%--这个css样式我没有,展示就简朴一点吧<link rel="stylesheet" href="<%=request.getContextPath()%>/resources/css/main.css" type="text/html">--%>
	
	    <!--引入本地jQuery-->
	    <script type="text/javascript" src="<%=request.getContextPath()%>/resources/js/jquery-1.11.3.min.js"></script>
	</head>
	
	<script>
	    jQuery(function($){
    
     
	        var urlStr = "<%=request.getContextPath()%>/courses/<%=request.getParameter("courseId")%>";
	        //alert("Before Call: " + urlStr);
	        $.ajax({
    
     //通过ajax异步从服务端拿到json数据并动态加载页面
	            method: "GET",
	            url: urlStr,
	            success: function(data, status, jqXHR){
    
     
	                //alert("Success: " + data);
	                var course = data;
	                var path = "<%=request.getContextPath()%>/";
	                $(".course_title").text(course.courseTitle);
	                $(".course_info").text(course.courseDesc);
	                $(".course_imgPath").attr("src", path+course.imgPath);
	                $("#course_duration").text(course.courseDuration);
	            }
	        });//end ajax
	    });
	</script>
	
	<body>
	<p>This is MvcHome, your world!</p>
	<h3 class="course_title"></h3>
	<h3 class="course_info"></h3>
	<h3 id="course_duration"></h3>
	<div><img class="course_imgPath"/></div>
	</body>
	</html>

springmvc拦截器

拦截器是指通过统一拦截从浏览器发往服务器的请求来完成功能的增强,解决请求的共性问题(乱码、权限验证等问题)

springmvc过滤器也能起到一定的拦截器作用

拦截器的实现:

  • 1.编写拦截器类实现HandlerInterceptor接口(WebRequestInterceptor接口也可以,但不常用)
  • 2.将拦截器注册进SpringMVC框架中(mvc-dispatcher-servlet.xml)
  • 3.配置拦截器的拦截规划

过滤器与拦截器的区别:

  • 过滤器Filter依赖于Servlet容器,基于回调函数,过滤范围大

  • 拦截器Interceptor依赖于框架容器,基于反射机制,只拦截请求

MyBatis入门

通过自动回复机器人学Mybatis

mybatis的特点

1.sql语句与代码分离。优点:便于管理和维护;缺点:不便于调试,需要借助日志工具获得信息

2.用标签控制动态sql语句的拼接。优点:用标签代替编写逻辑代码;缺点:拼接复杂sql语句时,没有代码灵活,比较复杂

3.结果集与java对象的自动映射。优点:保证名称相同可自动映射;缺点:对开发人员所写的sql依赖性很强

4.编写原生sql。优点:接近JDBC,很灵活;缺点:对sql语句依赖很高(不同数据库sql语句可能不相同),半自动,数据库移植不方便

案例分析:
  • 基本功能

    接受发送指令

    根据指令自动回复对应的内容

  • 模块划分

    回复内容列表

    回复内容维护–后台新建、更改、删除指令及对应回复的维护界面

    对话功能

    回复内容删除

  • 项目开发流程(当然,每个人的开发顺序可能都不同)

1583754163

一、实战第一步–回复内容列表模块

在没有 Mybatis的情况下,完整的Jsp + Servlet + Jdbc实现案例中的回复内容列表模块,流程如下。

1.数据库建表

2.写一个jsp前端界面

3.servlet:

  • web.xml中注册一个servlet并建立映射请求

  • 写一个servlet类继承HttpServlet,重写doGet、doPost方法,用:访问数据库并把数据传给jsp。

4.代码重构下:bean装数据实体、dao层jdbc数据库增删改查、service业务操作、servlet是前后端页面控制

下面是最简单完整的Jsp + Servlet + Jdbc实现代码,工程名MicroMessage_jdbc。

1583754180

bean.Message:

​```java
package com.braincao.bean;

/**

  • @FileName: Message
  • @Author: braincao
  • @Date: 2018/11/18 23:18
  • @Description: 与数据库信息对应的实体类
  •  一个表对应一个类、表中的一个列属性对应一个成员
    

*/

public class Message {
//主键
private String id;

//指令名称
private String  command;

//描述
private String description;

//内容
private String content;

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public String getCommand() {
    return command;
}

public void setCommand(String command) {
    this.command = command;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

public String getContent() {
    return content;
}

public void setContent(String content) {
    this.content = content;
}

}


dao.MessageDao:

```java
package com.braincao.dao;
	
import com.braincao.bean.Message;
	
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
	
/**
 * @FileName: MessageDao
 * @Author: braincao
 * @Date: 2018/11/19 15:42
 * @Description: 使用jdbc访问数据库,和message表相关的数据库操作
 */
	
public class MessageDao {
    /**
     * 根据查询条件查询消息列表
     * @param : 查询条件:command指令名称、description描述
     * @return : 根据查询条件查询到的结果
     */
    public List<Message> queryListMessage(String command, String description){
        List<Message> messageList = new ArrayList<>();//把查询出来的结果放在这里
        try {
            //连接jdbc数据库
            Class.forName("com.mysql.jdbc.Driver");
            //下面一定要再jdbc的数据库连接地址后面加?useUnicode=true&characterEncoding=UTF-8,否则查询不到,编码问题
            Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/micro_message?useUnicode=true&characterEncoding=UTF-8", "root", "123456");
	
            //拼接查询语句
            StringBuilder sql = new StringBuilder("SELECT ID, COMMAND, DESCRIPTION, CONTENT FROM message WHERE 1=1");
            List<String> paramList = new ArrayList<>();
            if(command!=null && !"".equals(command.trim())){//查询
                sql.append(" AND COMMAND= ?");
                paramList.add(command);
            }
            if(description!=null && !"".equals(description.trim())){//查询
                sql.append(" AND DESCRIPTION LIKE '%' ? '%'");//%是sql的通配符,类似于*
                paramList.add(description);
            }
            PreparedStatement statement = conn.prepareStatement(sql.toString());//防止sql注入
            for(int i=0; i<paramList.size(); ++i){//给之前的sql语句中的 ? 赋值
                statement.setString(i+1, paramList.get(i));
            }
            //执行sql查询语句,将查询到的结果添加到messageList列表中
            ResultSet rs = statement.executeQuery();
            while(rs.next()){
                Message message = new Message();
                message.setId(rs.getString("ID"));
                message.setCommand(rs.getString("COMMAND"));
                message.setDescription(rs.getString("DESCRIPTION"));
                message.setContent(rs.getString("CONTENT"));
                messageList.add(message);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        //返回查询结果
        return messageList;
    }
}

service.ListService:

package com.braincao.service;
	
import com.braincao.bean.Message;
import com.braincao.dao.MessageDao;
	
import java.util.List;
	
/**
 * @FileName: ListService
 * @Author: braincao
 * @Date: 2018/11/19 15:50
 * @Description: 和message表相关的业务操作
 */
	
public class ListService {
   
    
    public List<Message> queryListMessage(String command, String description){
   
    
        MessageDao messageDao = new MessageDao();
        return messageDao.queryListMessage(command, description);
    }
}

servlet.ListServlet:

package com.braincao.servlet;
import com.braincao.service.ListService;
	
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * @FileName: ListServlet
 * @Author: braincao
 * @Date: 2018/11/18 21:15
 * @Description: 列表页面初始化控制的servlet,使用jdbc访问数据库
 */
	
@SuppressWarnings("serial")
public class ListServlet extends HttpServlet {
   
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
    
        //设置编码格式
        req.setCharacterEncoding("UTF-8");
	
        //接受页面的值
        String command = req.getParameter("command");
        String description = req.getParameter("description");
        //向页面传值
        req.setAttribute("command", command);
        req.setAttribute("description", description);
	
        //查询消息列表并传给前端页面
        ListService listService = new ListService();
        req.setAttribute("messageList", listService.queryListMessage(command, description));
        req.getRequestDispatcher("/WEB-INF/jsps/back/list.jsp").forward(req, resp);//把数据传给前端jsp
    }
	
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
   
    
        this.doGet(req, resp);
    }
}

前端list.jsp:

<!DOCTYPE html PUBLIC "-//W3C//DTD//XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
	
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>留言评论功能</title>
    <link 
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Pop_Rain/article/details/104818643

智能推荐

python编码问题之encode、decode、codecs模块_python中encode在什么模块-程序员宅基地

文章浏览阅读2.1k次。原文链接先说说编解码问题编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。 Eg:str1.decode('gb2312') #将gb2312编码的字符串转换成unicode编码str2.encode('gb2312') #将unicode编码..._python中encode在什么模块

Java数据流-程序员宅基地

文章浏览阅读949次,点赞21次,收藏15次。本文介绍了Java中的数据输入流(DataInputStream)和数据输出流(DataOutputStream)的使用方法。

ie浏览器无法兼容的问题汇总_ie 浏览器 newdate-程序员宅基地

文章浏览阅读111次。ie无法兼容_ie 浏览器 newdate

想用K8s,还得先会Docker吗?其实完全没必要-程序员宅基地

文章浏览阅读239次。这篇文章把 Docker 和 K8s 的关系给大家做了一个解答,希望还在迟疑自己现有的知识储备能不能直接学 K8s 的,赶紧行动起来,K8s 是典型的入门有点难,后面越用越香。

ADI中文手册获取方法_adi 如何查看数据手册-程序员宅基地

文章浏览阅读561次。ADI中文手册获取方法_adi 如何查看数据手册

React 分页-程序员宅基地

文章浏览阅读1k次,点赞4次,收藏3次。React 获取接口数据实现分页效果以拼多多接口为例实现思路加载前 加载动画加载后 判断有内容的时候 无内容的时候用到的知识点1、动画效果(用在加载前,加载之后就隐藏或关闭,用开关效果即可)2、axios请求3、map渲染页面4、分页插件(antd)代码实现import React, { Component } from 'react';//引入axiosimport axios from 'axios';//引入antd插件import { Pagination }_react 分页

随便推点

关于使用CryPtopp库进行RSA签名与验签的一些说明_cryptopp 签名-程序员宅基地

文章浏览阅读449次,点赞9次,收藏7次。这个变量与验签过程中的SignatureVerificationFilter::PUT_MESSAGE这个宏是对应的,SignatureVerificationFilter::PUT_MESSAGE,如果在签名过程中putMessage设置为true,则在验签过程中需要添加SignatureVerificationFilter::PUT_MESSAGE。项目中使用到了CryPtopp库进行RSA签名与验签,但是在使用过程中反复提示无效的数字签名。否则就会出现文章开头出现的数字签名无效。_cryptopp 签名

新闻稿的写作格式_新闻稿时间应该放在什么位置-程序员宅基地

文章浏览阅读848次。新闻稿是新闻从业者经常使用的一种文体,它的格式与内容都有着一定的规范。本文将从新闻稿的格式和范文两个方面进行介绍,以帮助读者更好地了解新闻稿的写作_新闻稿时间应该放在什么位置

Java中的转换器设计模式_java转换器模式-程序员宅基地

文章浏览阅读1.7k次。Java中的转换器设计模式 在这篇文章中,我们将讨论 Java / J2EE项目中最常用的 Converter Design Pattern。由于Java8 功能不仅提供了相应类型之间的通用双向转换方式,而且还提供了转换相同类型对象集合的常用方法,从而将样板代码减少到绝对最小值。我们使用Java8 功能编写了..._java转换器模式

应用k8s入门-程序员宅基地

文章浏览阅读150次。1,kubectl run创建pods[root@master ~]# kubectl run nginx-deploy --image=nginx:1.14-alpine --port=80 --replicas=1[root@master ~]# kubectl get podsNAME READY STATUS REST...

PAT菜鸡进化史_乙级_1003_1003 pat乙级 最优-程序员宅基地

文章浏览阅读128次。PAT菜鸡进化史_乙级_1003“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。得到“答案正确”的条件是: 1. 字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符; 2. 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或..._1003 pat乙级 最优

CH340与Android串口通信_340串口小板 安卓给安卓发指令-程序员宅基地

文章浏览阅读5.6k次。CH340与Android串口通信为何要将CH340的ATD+Eclipse上的安卓工程移植到AndroidStudio移植的具体步骤CH340串口通信驱动函数通信过程中重难点还存在的问题为何要将CH340的ATD+Eclipse上的安卓工程移植到AndroidStudio为了在这个工程基础上进行改动,验证串口的数据和配置串口的参数,我首先在Eclipse上配置了安卓开发环境,注意在配置环境是..._340串口小板 安卓给安卓发指令