Skip to content

JavaWeb

此教程是为了理解 Jeecg-库存管理网站 的后端部分,只需普通的 HTTP 单次请求

如果希望制作 Chatbot(会话/即时交互),建立连接--多次交互--断开,即需要搭建 Socket 长连接(TCP/IP),建议使用 Socket.IO

推荐SpringBoot清晰教程

工具

概念

MVC

       Model   处理数据逻辑----JavaBean
  Controller   对请求选择合适的Model和View----Servlet (url)
       View    用于数据展示、与用户交互----前端

规范-SSM框架

SSM = Spring + SpringMVC + MyBatis 概览

  MyBatis   持久层       与数据库进行交互,增删改查
   Spring   业务逻辑层    Model  应用的核心框架,管理对象及其生命周期
SpringMVC   表现层       Controller+View 处理用户界面和交互逻辑
-- 获得的POJO MyBatis 项目中(见SSM教程)
Dao 封装对数据库的操作:增删改查 Entity:严格对应数据库表的字段 设置SQL语句的Mapper
Service Do something Domain/Model:综合/节选多张表的字段与信息 Service接口 -> Impl实现类 -> Bean
Controller 根据url请求参数,调用不同的 Service View:发送给前端展示的字段 @Controller

注: POJO 指普通Java对象,包括私有字段、对应的 getter/setter

Cookie/SessionID/Token

假设用户登陆后,需要维持一段时间的登录状态,可有如下三种选择。

  1. 登录成功后,Server 向浏览器发送简单 Cookie,此后用户每次发送请求都 Request + Cookie {username:xx};随后,Server 根据 Cookie 中的用户名获取对应的登录信息

    • 由于 Cookie 仅存储于浏览器中,有被篡改的风险
    • ...
  2. 登录成功后,Server 对此次登录生成 SessionID、发送给浏览器,此后用户每次发送请求都 Request + Cookie {SessionID};随后,Server 根据 Cookie 中的 SessionID 获取对应的用户和登录信息

    • 多台服务器的情况下,登录信息可能不能共通
  3. 登录成功后,JWT 加密 algorithm - userinfo - signature 生成 Token 发送给浏览器,此后用户每次发送请求都带上 {Authorization:token};随后,Server 进行解密、检查 signature 后决定放行

注:关于对文件/信息进行加密

keygen() -> (public_key, private_key)

encrypt(PlainT, public_key) -> Cipher         //非对称加密
decrypt(Cipher, private_key) -> PlainT

sign(Msg, private_key) -> signature           //对文件进行签名
varify(Msg, signature, public_key) -> OK? 

encrypt(PlainT, key) -> Cipher                //对称加密
decrypt(Cipher, key) -> PlainT

教程导航

  • Tips
    • 右键目录,选择生成class/servlet/..
    • 右键 或 Alt+Insert 自动生成类的 Getter/Setter 等代码
    • 右键--Project Structure--Facets--点击项目--点击标红目录进行自动创建
    • 非java代码都放在resources文件夹中

黑马程序员JavaWeb基础教程

基础JavaEE,有助于了解概念和技术发展

  • JDBC API (mysql-connector-java) 是 java 与 MySQL 交互的接口,进一步可使用 Druid 连接池分配程序与数据库间的 connection

  • MyBatis 是一款持久层框架,简化了JDBC操作:将配置放在config中,SQL语句放在mapper中

mybatis-config.xml |  mapper resource="UserMapper.xml"
UserMapper.xml     |  <select id="selectAll" ...>SQL</select>
User.java          |  public class User {...}
UserMapper.java    |  public interface UserMapper {List<User> selectAll();}
Demo.java          |  UserMapper mm = session.getMapper(UserMapper.class);
                   |  List<User> uu = mm.selectAll();

可用注解代替xml,此外,MyBatis 提供SQL 语句构建器

public interface UserMapper{
    @Select("select * from tbl where age = #{age}")
    List<User> selectByAge(int age);
}
  • Tomcat部署web项目: 作为容器创建Servlet对象

    • 打包Maven项目后部署在Tomcat中,注意:pom.xml 添加 <packaging>war</packaging>,否则默认打包 .jar
    • 也可以集成至Idea:运行标志边上(下拉栏)--Edit Configuration--Run/Debug Configuration--ADD符号--Tomcat Server--Local--Configure--Server Tab--设置Home--Deployment Tab--ADD符号--xxx.war--OK--Apply--运行标志
    • 也可以以Maven插件的方式集成至当前项目:pom.xml 添加相关依赖--Run Maven--tomcat:run
    • 也可内置于springboot中
  • A Servlet is a small Java program that runs within a Web server, 由 JavaEE 提供规范接口

    • Servlet在容器中运行,其生命周期由容器管理:第一次访问--加载/实例化--init()--处理请求--destroy()
    • Servlet(接口)--- GenericServlet(抽象实现类)--- HttpServlet(封装HTTP协议后的实现类)
@WebServlet(urlPatterns = {"/login"})
public class Demo implements Servlet{
    public void init(ServletConfig config) throws ServletException{...}
    public void service(ServletRequest req, ServletResponse res){

        String name = req.getParameter("name");

        res.setHeader("content-type","text/html;charset=utf-8");
        res.getWriter().write('<h1>Hello</h1>');
        }
    public void destroy(){...}
    public ServletConfig getServletConfig(){...}
    public String getServletInfo(){...}
    ...
}

开发者的自定义Servlet一般 extends HttpServlet: doGet()/doPost(),二者通用:

Map<String,String[]> map= httpReq.getParameterMap()
           String[] val = httpReq.getParameterValues(String name)
             String par = httpReq.getParameter(String name)

转发getRequestDispatcher v.s. 重定向sendRedirect 的实现;以及路径中何时需要加虚拟目录

Response 非纯文本情况下不能 res.getWriter().write,需要先将其转变为字节流:

FileInputStream fis = new FileInputStream('a.png');
ServletOutputStream os = httpRES.getOutputStream();
// 从File流拷贝至Servlet流
byte[] buff = new byte[1024];
int len = 0;
while ( (len = fis.read(buff))!= -1 ){
    os.write(buff,0,len);
}
fis.close();

黑马Spring教程 + SSM教程

  • 为什么要用 BeanIoC、DI、AOP 以降低对象间耦合度

  • Spring-AOP 配置方法,AOP工作流程,AOP切入点表达式(支持通配符)Spring AOP 五大通知类型

  • 记得引入xml-header部分的xmlns、xsi,以及pom中相关依赖

  • 通过BeanFactory配置/创建/管理Beans,步骤

    1. 简单创建一个Maven项目后,配置 spring-context
    2. 创建 UserService 接口
    3. UserServiceImpl 是 UserService 的实现类(可配置为Bean)
    4. IDEA 右键目录 New 一个 XML Configuration File,配置 <bean id="userService" class="xx.xx.impl.UserServiceImpl">...</bean>
    5. 如果某Bean中还需要引用另一个Bean,例如
      • ...处增加: <property name="bean2" ref="bean2"></property>
      • autowire="byName":实现类中设定setBean2(Bean2 bean2)方法,寻找容器中name/id=bean2者,自动注入
      • autowire="byType":寻找容器中类型为Bean2类型者,若有重复则会报错,e.g.当Bean2接口对应两个Impl实现类,配置成两个Bean
    6. 如果是有参构造,例如class XImpl的构造方法public XImpl(String argname){},则...处增加: <constructor-arg name="argname" value="123"></constructor-arg>
    7. 总结:ref="BeanXxx", value=String/int/boolean, 如果需要注入的是ref/value的List,则 <property name="xxx"> <list> <value>aaa</value> <value>bbb</value> </list> </property>
// 创建工厂对象
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 读取xml
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("beans.xml");
// 根据id获取Bean实例对象 -- 首次调用getBean()时才将被调用的Beans实例化、初始化
UserService userService = (UserService) beanFactory.getBean("serv1");
  • ApplicationContext (Spring容器) 中封装了BeanFactory,并且扩展了功能API(监听、国际化等),getBean方法
// 创建容器 -- 此时就将Beans实例化、初始化
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) applicationContext.getBean("serv1");   // bean xml的优先顺序:(name1,name2)>id>class
  • 设定test/dev环境

    • 希望使用大标签<beans profile="dev">....bean1234....</beans>内的Beans
    • 则main方法中 System.setProperty("spring.profiles.active","dev")
  • 有时项目过大,可以吧Beans分开写进不同的xml中,然后<import resource="classpath:aa.xml"></import>至相关<beans>大标签中

  • 许多外部包提供非自定义的Beans,JDBC组件库Druid示例如下;Mybatis-SqlSessionFactory同理,其InputStream可设置为静态BeanFactory

// main函数中,Druid的正常用法
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://xxx:port/xxx");
dataSource.set....

// <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
// dataSource.setXxx等改为在 <property> 标签中设置(如果是构造对象时就需要的参数,使用<constructor-arg>,例如返回Connection的DriveManager.getConnection方法)
// xml中进行以上设置后,main改为:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Object dataSource = applicationContext.getBean("dataSource");
// xml中  <context:component-scan base-package="com.proj"/>
@Component("beanName") //get时byName,不填则需byType
public class UserServiceImpl implements UserService {...}
@Controller
public class UserController{
    @RequestMapping(value="/users/{}",method=RequestMethod.DELETE)      // 访问/users/1 意味着输入形参id=1
    @ResponseBody                                                       // 设置响应内容为当前返回值,无需解析(建议返回json格式)
    public String delete(@PathVariabla Integer id){                     //  /users/1?name=aa&age=bb可提供name、age两个形参
        return "{'val':'ok'}"                                           // 
    }

    @RequestMapping("/users")                                            // /users?name=aa&age=22可提供name、age两个形参
    @ResponseBody                                                      
    public String test(@RequestParam("name") String userName,int age){  // 形参名一致可直接输入,但不一致则用RequestParam绑定关系
        return "{'val':'ok'}"                                            // 也可直接接收POJO对象 User{name='aa',age='22'} 
    }                                                                   // String[] 直接接收数组 v.s. @RequestParam List<String> 给集合对象赋值
}
// .yaml中  lesson:abc
@RestController
@RestMapping("/ab")
public class AbController{
    @Value("${lesson}")         //从.yaml中获取lesson取值
    private String lesson;

    @GetMapping("/{id}")
    public String test(@PathVariabla Integer id){
        System.out.println(lesson);    
        return "ok";
    }
}
  • MyBatisPlus 进一步简化了MyBatis,使用步骤
    1. 生成一个SpringBoot项目:IDEA 勾选 Spring Initializr---web---Spring web,---SQL---MyBatis Framework,---SQL---MySQL Driver
    2. application.yml 配置数据源
    3. 定义数据层接口映射配置(教程所例的BaseMapper接口提供了基本CRUD操作接口)
@Mapper
public interface UserDao{
    @Select("select * from user where id=#{id}")
    public User getById(Long id);
}

参考